vue history模式在nginx下错误的解决方案

前言


众所周知 vue 默认的路由为 hash 模式,在 URL 上面会带一个#号,然而某些时候并不是我们想要的。如何去掉#号?去掉#号后的一些问题如何处理?下面我们简单探讨下这块内容。

使用 history 模式

如果不想要很丑的 hash,我们可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成 URL 跳转而无须重新加载页面。

  • 修改路由模式
1
2
3
4
const router = new VueRouter({
mode: 'history',
routes: [...]
})
  • 修改 config/index.js

config/index.js 中 build 下的 assetsPublicPath 从’./‘改成’/‘

1
2
3
4
5
6
7
8
9
module.exports = {
build: {
env: require('./prod.env'),
index: path.resolve(__dirname, '../dist/index.html'),
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
productionSourceMap: true,
..... 其他代码略

在 nginx 下的配置

Apache

1
2
3
4
5
6
7
8
 <IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
</IfModule>

除了 mod_rewrite,你也可以使用 FallbackResource

nginx

1
2
3
 location / {
try_files $uri $uri/ /index.html;
}

原生 Node.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const http = require('http');
const fs = require('fs');
const httpPort = 80;

http
.createServer((req, res) => {
fs.readFile('index.htm', 'utf-8', (err, content) => {
if (err) {
console.log('We cannot open "index.htm" file.');
}

res.writeHead(200, {
'Content-Type': 'text/html; charset=utf-8'
});

res.end(content);
});
})
.listen(httpPort, () => {
console.log('Server listening on: http://localhost:%s', httpPort);
});

详细配置见官方配置

404 的解决方案

第一种方式见上面–在 nginx 下的配置,还是贴一下:

1
2
3
location / {
try_files $uri $uri/ /index.html;
}

第二招,逻辑类似

1
2
3
4
5
6
7
8
location / {
root /data/nginx/html;
index index.html index.htm;
if (!-e $request_filename) {
rewrite ^/(.*) /index.html last;
break;
}
}

第三式,直接转发到 index.html

1
2
3
4
5
location / {
root /data/nginx/html;
index index.html index.htm;
error_page 404 /index.html;
}

第四招,类似第二招

1
2
3
4
5
6
7
8
 location / {
root html;
try_files $uri $uri/ @router;
index index.html index.htm;
}
location @router {
rewrite ^.*$ /index.html last;
}

Uncaught SyntaxError: Unexpected token <错误

配置好了刷新后一片空白?打开控制台一看什么鬼,Uncaught SyntaxError: Unexpected token <错误?

貌似是 JS 的错误,下面我们逐一排查。

  • 错误排查

检查配置有没有问题:

  1. 检查 config/index.js 中 build 下的 assetsPublicPath 是否正确?
1
2
3
4
5
6
7
8
9
module.exports = {
build: {
env: require('./prod.env'),
index: path.resolve(__dirname, '../dist/index.html'),
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
productionSourceMap: true,
..... 其他代码略
  1. 检查模式是否为 history
1
2
3
4
const router = new VueRouter({
mode: 'history',
routes: [...]
})
  1. 检查路由路径
    你的子路径需要加上去,给每一个 component 加上 name,例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const router =  new Router({
mode: 'history',
routes: [
{
path: '/',
component: Index,
name: 'index',
redirect: '/home',
children: [{
path: 'home', //这里会不会有问题?
component: Home
},
{
path: 'goodsDetails', //子路径需要配完整,应该是/home/goodsDetails
component: goodsDetails
},
}
]
})

以上都检查完,打包重新部署看看

  • 修复问题
    如果还有问题,试试下面的配置,其实 js、css、png 文件我们不需要转到 index.html
1
2
3
4
5
location / {
root html;
rewrite ^.+(?<!js|css|png|map)$ /index.html break;
index index.html index.htm;
}

结语

遇到问题,先分析下具体的原因,一步一步排查,总归还是有解决办法的。出现 404,空白页,JS 问题,总觉得是我们前端哪儿有问题,排查完才发现是配置问题,以上几招供大家参考,能解决问题的方法就是好方法!

×

纯属好玩

扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

文章目录
  1. 1. 前言
    1. 1.1. 使用 history 模式
    2. 1.2. 在 nginx 下的配置
    3. 1.3. 404 的解决方案
    4. 1.4. Uncaught SyntaxError: Unexpected token <错误
  2. 2. 结语
,