最近有个 Vue 项目,是使用 Vue-cli 构建起来的。Vue-Router 是使用的 HTML5 History 模式。这个模式是使用浏览器提供的 History 接口实现的,所以如果是在页面上通过点击链接往里面 push 一个新地址是没问题的,但是如果直接请求这个地址则会 404 (因为这个地址并不是真实存在的,只是我们通过代码模拟出来的)。
所以 Vue-Router 的手册中也给出了解决方式:通过配置重写规则把 404 统一重定向到 index.html 文件。但是懒得自己配环境,所以直接用的 Netlify 提供的免费服务。
当然 Netlify 很强大,提供了 redirect 的功能,是通过添加 _redirects
规则文件到根目录下来实现的。具体可以参照:https://www.netlify.com/docs/redirects/
问题就是如何在 npm run build
的时候自动把 _redirects
文件添加到根目录呢?
.
├── build
├── config
├── node_modules
├── src
└── static
5 directories
上面的是由 vue-cli 所构建出来的项目的目录结构。起初我尝试把 _redirects
放到 static
目录中,但是失败了。是因为 npm run build
后 static
目录中的文件并不是放到了根目录(这里是 dist
)中,而是在根目录中的 static
目录内。
dist
├── index.html
└── static
├── _redirects <-- 在这里
├── css
├── fonts
└── js
4 directories, 10 files
于是我 Google 了一圈,找到了这个 issues :https://github.com/vuejs/vue-cli/issues/285,但是这貌似也不是我想要的。所以没办法了,只能自己动手了。
看了眼 package.json
文件里的 build 是执行了 node build/build.js
,打开这个文件一直跟踪到了 build/webpack.prod.conf.js
文件里,在 90 行左右有这样的代码:
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
ignore: ['.*'],
},
])
使用了 CopyWebpackPlugin 这个插件把 static 中的文件拷贝到了 config.build.assetsSubDirectory
下。
assetsSubDirectory 的定义在 config/index.js
文件中,应该就是指向了 dist/static
这个目录。
module.exports = {
build: {
env: require('./prod.env'),
index: path.resolve(__dirname, '../dist/index.html'),
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static', // <-- 在这里
assetsPublicPath: '/',
productionSourceMap: true,
// ....
所以我就改了一下 build/webpack.prod.conf.js
的代码:
+ // copy _redirects file
+ new CopyWebpackPlugin([
+ {
+ from: path.resolve(__dirname, '../static/_redirects'),
+ to: config.build.assetsSubDirectory + '/..'
+ }
+ ]),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
- ignore: ['.*']
+ ignore: ['.*', '_redirects']
}
])
把 _redirects
文件复制到 dist/static 的上级目录 /..
中。完成啦~
这种修改文件的方法可能是最简便的了,但是随便修改这些文件显得不是很专业嘛。所以大家如果有别的方法请告诉我。