webpack的常用基本配置我们可能已经耳熟能详,比如
input,output,module,plugins,devServer的配置等等。而在这些基本配置中,其实还有一些细节参数,它可以帮助我们更好的定制化打包的目录结构,但它可能并不是那么好理解,比如publicPath。
webpack官网这么解释:publicPath配置项在很多场景下都非常有用,它允许你给你的应用中的所有静态资源指定一个基本路径。
The publicPath configuration option can be quite useful in a variety of scenarios. It allows you to specify the base path for all the assets within your application.
有些抽象,我总结了下,它大概做的事情就是:可以帮我们处理资源引用的url路径问题:为生成的资源自动添加特定路径前缀。
什么时候需要使用publicPath?
1. 打包出来的文件有特定目录结构划分时
webpack打包出来的文件,默认都统一放在output配置的path路径下,项目稍大一点,这个目录中的文件就比较杂乱了,我们可能会希望给这些文件进行归类。当然我们可以粗暴一点通过filename来指定一个子目录。但是,如果在这这个子目录中,文件还有层级,就需要配置相应 plugin 或者 loader 的 publicPath 了。
例如file-loader,我们可以配置它的outputPath 自定义生成文件存放在output.path的哪个子目录,并且配置它的 publicPath 指定资源路径前缀:
在file-loader中publicPath的值可以是string和function1
2
3
4
5
6
7
8
9
10
11
12module: {
  rules: [
    {
      test: /\.(png|jpe?g|gif)$/i,
      loader: 'file-loader',
      options: {
        outputPath: 'media', // string
        publicPath: 'media', // string
      }
    }
  ]
}
这样,编译打包后的图片资源就会放在dist/media目录下(假设你设置的output path为dist),并且所有引用到图片的资源路径都会自动加上前缀 media/。
如果想对不同的图片添加不同的路径前缀,可以使用函数来定义publicPath:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27module: {
  rules: [
    {
      test: /\.(png|jpe?g|gif)$/i,
      loader: 'file-loader',
      options: {
        publicPath: (url, resourcePath, context) => {
          // `resourcePath` 是这个资源的本地绝对路径
          // `context` 是存放这个资源的目录,或者是`context`配置项的值
          // 想获取相对路径可以这样:
          // const relativePath = path.relative(context, resourcePath);
          // 将符合下面条件的png图片url添加前缀 `other_public_path`
          if (/my-custom-image\.png/.test(resourcePath)) {
            return `other_public_path/${url}`;
          }
          // 将符合下面条件的图片url添加前缀 `image_output_path`
          if (/images/.test(context)) {
            return `image_output_path/${url}`;
          }
          // 其他图片url添加前缀 `public_path`
          return `public_path/${url}`;
        }
      }
    }
  ]
}
这样编译打包出来的图片url,就会根据你的设置,分别加上 other_public_path、image_output_path和public_path前缀了(当然这几个目录的名称你自己来定),是不是很不错?
2. 生产模式要求index首页不在根目录下
例如在某些生产模式下,要求产出的文件目录类似这样:1
2
3
4
5|--assets/
|    |--index.js
|    |--vendor.js
|--page/
     |--index.html
那么可以这么配置webpack:1
2
3
4
5
6
7
8
9
10
11
12// webpack.prod.js file
output: {
    filename: 'assets/[name].js', 
    path: resolve(__dirname, '../', 'dist'),
    publicPath: '../' // 相对HTML页面的路径
},
plugins: [ 
    new HtmlWebpackPlugin({
        template: '../public/index.html',
        filename: 'pages/index.html'
    })
],
编译后,在index.html中index.js的引用就会变成这样:1
<script src=../assets/index.js></script>
在
output中publicPath的值可以是以下几种:
2
3
4
5
6
7
8
9
10
11
12
//...
output: {
// 以下几种之一
publicPath: 'https://cdn.example.com/assets/', // CDN (一定是HTTPS)
publicPath: '//cdn.example.com/assets/', // CDN (HTTPS协议)
publicPath: '/assets/', // 相对服务端跟目录
publicPath: 'assets/', // 相对 HTML 页面文件
publicPath: '../assets/', // 相对 HTML 页面文件
publicPath: '', // 相对 HTML 页面文件 (与HTML同一目录)
}
};
3. 生产模式下的静态资源在CDN上托管时
例如在某些生产模式下,静态文件都由www.xx.com/assets来托管
那么可以在 webpack 中这么配置 publicPath:1
2
3
4
5
6// webpack.prod.js file
output: {
    filename: 'assets/[name].js', 
    path: resolve(__dirname, '../', 'dist'),
    publicPath: 'https://www.xx.com/assets' // CDN URL
},
编译后,在 index.html 中 index.js 的引用就会变成这样:1
<script src=https://www.xx.com/assets/index.js></script>
其他
在devServer中也有publicPath配置,默认它是获取output的publicPath的值。
要提一下,webpack-dev-server生成的文件是不会放在硬盘的,而是在内存中,所以看不到。只有在请求资源的时候,可以证明文件的存在。。。1
2
3devServer {
  publicPath: '/assets/'
}
一定要在string的前后都放上
/。
需要注意的是,devServer中还有一个叫做contentBase的参数,这个参数如果配置的不好,跟publicPath一搭配,很可能会导致请求不到页面(我也是被这个坑了很久)。这个地方如果出问题,基本上原因在于contentBase设置的路径范围太小了,去掉contentBase配置,或者给它配置多个路径,把输出目录包含进来,就可以解决问题。
| 1 | devServer { | 
–
GOOD LUCK!
参考:
https://webpack.js.org/guides/public-path/
https://www.npmjs.com/package/file-loader