对于 Webpack 中的路径的理解

Webpack 概念理解

Posted by Nicodechal on 2020-01-14

Webpack 打包工具涉及很多的路径的设置,本文对其中的路径进行分析和总结。

Webpack 中的路径

Webpack 中涉及到的路径:

Webpack 打包相关的全局路径

  • output.path
    一个绝对路径,指定打包文件的输出文件夹,(默认值:path.join(process.cwd(), 'dist'))。打包文件指的是经过 Webpack 处理得到的文件。
    这里就是指定了文件打包后会放在哪里,不再赘述。
  • output.publicPath
    用于生成使用浏览器访问打包文件的输出文件夹时的访问路径。这个值影响的是打包之后文件中使用的各种路径。例如 CSS 文件中的 url(),或生成的 HTML 文件 (如果使用了 HtmlWebpackPlugin, 这个插件会在输出文件夹下生成 index.html 文件,并自动引用生成的 bundle 文件) 中打包文件的访问路径。

举个例子:

1
2
3
4
5
6
7
8
...
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: '/packed/',
},
...
plugins: [new HtmlWebpackPlugin()],

这个例子会将文件打包后放进项目的 dist 文件夹,打包会产生 dist/index.htmldist/bundle.js。此时 index.html 会自动生成 使用浏览器访问打包文件时的访问路径,由于这里指定了使用浏览器访问打包文件的输出文件夹时的访问路径 publicPath/packed/,因此生成的请求路径将以 /packed/ 开头,因此,index.html 中会生成一个 script 标签引用 bundle.js:

1
<script type="text/javascript" src="/packed/bundle.js"></script>

总的来说,publicPath 设置了,假如你有一台服务器,这台服务器访问打包文件时的请求链接的路径前缀。如果你的服务器写了路由,使得访问链接类似 /packed/* 时可以访问到打包的文件,那就需要设置 publicPath: '/packed/' 使 webpack 项目可以正常运行。

publicPath 默认值是 '',即 webpack 假设你的打包文件都在根路径下访问。

假设你的网站为 http://www.example.com,默认情况下 ( publicPath: '' ) ,你生成的 index.html 中的路径可能像这样:

1
<script type="text/javascript" src="bundle.js"></script>

此时,就需要你的服务器接收到请求 http://www.example.com/bundle.js 时可以访问到 bundle.js 文件。

也就是说,设置 publicPath 的目的在于使 webpack 导出的打包文件中生成的请求 URL 可以和你的服务器设置一致。

Loader 单独设置的路径

  • loader 中的 options.outputPath
    指定 loader 处理文件的输出文件夹,一般是相对于输出路径 output.path 的相对路径。
  • loader 中的 options.publicPath
    单独指定 loader 处理文件在浏览器中的访问路径。

这里 outputPath 指定了 loader 的输出文件的路径,通常是相对于 output.path 的路径。
这里的 publicPath 则单独指定了该 loader 处理的文件在浏览器中的访问路径。例如全局的 publicPath/packed/,但我想单独设置图片的请求 URL,则可以指定该项,实现对不同的文件的请求路径分别设置。比如我希望 bundle.js 的请求路径为 http://www.example.com/packed/bundle.js,而图片为 http://www.example.com/images/xxx.png,则可设置处理图片的 loader 的 publicPath/images/

webpack-dev-server 相关路径

  • devServer.contentBase
    指定不受 Webpack 处理的静态文件所在目录用于直接访问,推荐使用绝对路径。
  • devServer.publicPath
    指定 webpack 打包文件如果在浏览器中的访问需要使用的路径。这里设置的是服务器 (webpack-dev-server) 如何处理请求。如果未设置以 output.publicPath 为值。

devServer.contentBase 指定的是使用 webpack-dev-server 访问非打包静态文件的方式,例如指定该值为项目根目录下的 data 目录,则其中有一个文件 1.txt 使用 webpack-dev-server 可以通过路径 http://localhost:8080/1.txt 直接访问到该文件。该参数默认值为项目根目录,使用默认值时,使用 http://localhost:8080/data/1.txt 可以访问刚刚那个文件。

例如将 devServer.publicPath 值设为 /serve/,则如果要访问 bundle.js 时,需要访问的路径为 http://localhost:8080/serve/bundle.js。显然,如果 output.path/packed/,则打包时,文件中的路径为 /packed/bundle.js,此时发起的请求是 http://localhost:8080/packed/bundle.js,但是,服务器 (webpack-dev-server) 却是在 http://localhost:8080/serve/bundle.js 处理请求,因此访问 http://localhost:8080/packed/bundle.js 显然无法获得相应文件。

为了使 webpack-dev-server 正确工作,一般将 devServer.publicPath 设置为 output.publicPath

webpack-dev-server 运行时,会打印类似下面的 log:

1
2
3
ℹ 「wds」: Project is running at http://localhost:8080/ # 服务所在 url
ℹ 「wds」: webpack output is served from /packed/ # 由 publicPath 指定,优先级:1. devServer 2. output
ℹ 「wds」: Content not from webpack is served from /path_to_your_project # 由 contentBase 指定

参考之前的说明可以了解其含义。

参考资料

Webpack Configuration