webpack中涉及许多路径参数的配置。在此做个整理。
context
context是webpack编译时的基础目录,entry入口会相对于此目录查找。
若不配置,默认值是当前目录,webpack设置context、默认值代码:
this.set("context", process.cwd());
即webpack运行所在目录。
context应该是绝对路径,假设入口是src/main.js,则可以设置
{
context: path.resolve("./src")
entry: "./main.js"
}
context实际作用?
官方文档的解释是使得你的配置独立于工程目录 「This makes your configuration independent from CWD (current working directory)」。
怎么理解?
在分离开发和生产的配置文件时候,一般把webpack.config放到build文件夹下,此时entry却不用考虑相对于build目录来配置,仍相对于context。
output 的配置项和 context 没有关系,但是有些插件的配置项和 context 有关,后面会说明。
output
output.path
打包文件输出的目录,建议配置为绝对路径(相对路径不会报错),默认值和context默认值一样,都是process.cwd().
除了常规的配置方式,还可以在path中使用[hash]模版, 比如配置:
output: {
path: path.resolve('./dist/[hash:8]'),
filename: '[name].js'
}
这里的hash值是编译过程的hash,如果被打包进来的内容改变了,hash值也会发生改变。
这个可以用于版本回滚。你也可以设置为path.resolve(`./dist/${Date.now()}`)方便做持续集成等。
output.publicPath
一言以蔽之,下面的公式来表述
静态资源最终访问路径 = output.publicPath + 资源loader或者插件等配置路径
举例说明:
output.publicPath = '/static/'
//图片 url-loader配置
{
name: 'img/[name].[ext]'
}
//最终图片访问路径为
output.publicPath + 'img/[name].[ext]' = '/static/img/[name].[ext]'
// JS output.filename 配置
{
filename: 'js/[name].js'
}
//最终JS访问路径为
output.publicPath + 'js/[name].js' = '/static/js/[name].js'
// CSS
new ExtractTextPlugin('css/style.css');
//最终 CSS访问路径为
output.publicPath + 'css/style.css' = '/static/css/style.css'
常见的publicPath配置的实际意义
1.相对路径,实际上是相对于index.html。因为最终bundle.js是在index.html中通过相对路径引入。
相对路径的好处是本地可以访问,在一些混合app用的file协议,用绝对路径是不行的。
2.相对于url(//)或http地址(http://),使用此场景是将资源托管到CDN,比如公司的静态资源服务器等。
另外,publicPath应该以'/'结尾,同时其他loader或插件的配置不要以'/'开头。
webpack-dev-server
1.publicPath
这里的publicPath是用于开发环境,不会出现配置http地址的情况。
wds打包的内容是放在内存汇总,通过express匹配请求路径,然后读取对应的资源输出。
这些资源对外的根目录是publicPath,可以理解和output.path的功能一样,将所有资源放在此目录下,
在浏览器可以直接访问此目录下的资源。但是这个路径仅仅只是为了提供浏览器访问打包资源的功能,
webpack中的loader和插件仍然是取output.publicPath,比如CSS里面的图片最终的路径是"/static/img/xxx.png",
这也说为什么官方推荐publicPath和webpack配置的保持一致(除了http地址),配置一致菜鸟正常访问其他静态资源。
举例说明:
//webpack.config.js
output: {
path: path.resolve('./dist/'),
filename: 'js/[name].js',
publicPath: '/static/'
}
// api调用 webpack-dev-server
var webpack = require('webpack');
var webpackDevServer = require('webpack-dev-server');
var config = require('./webpack.config');
var compiler = webpack(config);
var server = new webpackDevServer(compiler, {
hot: true,
publicPath: '/web/'
});
server.listen(8282, '0.0.0.0');
如何查看webpack-dev-server所有启动后的资源访问路径呢?访问/webpack-dev-server。
你会发现,资源的路径都是/web/****,所以在index.html中引入js的路径应为/web/js/main.js,
同时style.css中图片的路径仍然为/static/img/***.png
html-webpack-plugin
这个插件的几处配置受路径配置影响。
template
template的路径是相对于output.context,源码如下:
this.optiobns.template = this.getFullTemplatePath(this.options.template, compiler.context);
因此template对应的文件需要放在output.context配置的目录下才被识别。
filename
filename的路径是相对于output.path,源码如下:
this.options.filename = path.relative(compiler.options.output.path, filename);
在webpack-dev-server中,则相对于webpack-dev-server配置的publicPath
若 webpack-dev-server 中的 publicPath 和 ouput.publicPath 不一致,在这种配置下使用html-webpack-plugin是有如下问题:
- 自动引用的路径仍然以 ouput.publicPath 为准,和 webpack-dev-server 提供的资源访问路径不一致,从而不能正常访问;
- 浏览 index.html 需要加上 webpack-dev-server 配置的 publicPath 才能访问(http://localhost:8282/web/)。
这两个问题也反推出了最方便的配置为:
- ouput.publicPath 和 webpack-dev-server 的publicPath 均配置为'/',vue-cli 就是这种配置
- template 放在根目录,html-webpack-plugin 不用修改参数的路径,filename 采用默认值。