Webpack中的"publicPath"是什么作用?

309

Webpack 文档 中阐述了 output.publicPath 是:

从 JavaScript 的视角看,output.path

您可以详细解释一下这实际上是什么意思吗?

我使用 output.pathoutput.filename 来指定 Webpack 应该输出结果的位置,但我不确定在 output.publicPath 中应该放置什么,以及是否需要此选项。

module.exports = {
  output: {
    path: path.resolve("./examples/dist"),
    filename: "app.js",
    publicPath: "What should I put here?"   
  } 
}

26
我想补充一下这个问题:什么时候应该使用 path,什么时候应该使用 publicPath - wmock
1
答案在这里:https://github.com/webpack/docs/wiki/configuration#outputpublicpath - mqklin
如果有帮助:http://tomasalabes.me/blog/_site/web-development/2016/12/10/Webpack-and-the-public-path.html - talabes
这里是Webpack2的文档:https://webpack.js.org/guides/public-path/。 - Eliran Malka
9个回答

187

output.path

本地磁盘目录,用于存储所有输出文件(绝对路径)

示例: path.join(__dirname, "build/")

Webpack 将所有内容输出到 localdisk/path-to-your-project/build/


output.publicPath

您上传捆绑文件的位置。 (绝对路径或相对于主 HTML 文件)

示例: /assets/

假设您在服务器根目录下部署了应用程序http://server/

通过使用/assets/,应用程序将在以下位置查找 webpack 资源:http://server/assets/。实际上,webpack 遇到的每个 URL 都会被重新编写,以始于“/assets/”。

src="picture.jpg" 重写 ➡ src="/assets/picture.jpg"

访问地址:(http://server/assets/picture.jpg)


src="/img/picture.jpg" 重写 ➡ src="/assets/img/picture.jpg"

访问地址:(http://server/assets/img/picture.jpg)


1
output.publicPath有一个'auto'选项。但除了烧掉额外的CPU周期以获得与普通'''./'相同的效果之外,它还能做什么呢?我不知道。谁知道呢? - Robert Siemer

75

当webpack在浏览器中执行时,需要知道您将生成的bundle托管在哪里。因此,它能够请求额外的块(使用代码分割时)或通过file-loaderurl-loader加载的引用文件。

例如:如果您配置http服务器将生成的bundle托管在/assets/下,则应编写:publicPath:"/assets/"


3
请问你能告诉我 assets 文件夹的位置吗?我想查看 assets 文件夹中的文件。谢谢。 - gauti

59
the publicPath is just used for dev purpose, I was confused at first time I saw this config property, but it makes sense now that I've used webpack for a while. Suppose you put all your js source files under 'src' folder, and you configure your webpack to build the source files to 'dist' folder with 'output.path'. But if you want to serve your static assets under a more meaningful location like 'webroot/public/assets', you can use 'output.publicPath='/webroot/public/assets'' so that in your HTML, you can reference your JS with ''. When you request 'webroot/public/assets/bundle.js', the 'webpack-dev-server' will find the JS under the 'dist' folder. Note that this option is useful not just during development, but also for asynchronously loading script bundles in production.

1
这不仅仅是为了开发目的,@jhnns的回答解释了它如何影响加载器输出。 - Wen
1
从这个链接 http://webpack.github.io/docs/configuration.html#output-publicpath 来看,这个选项告诉Webpack在生成的文件中填充正确的资产URL或路径,而不仅仅是为了中间件。当运行开发服务器时,我认为中间件会查看publicPath来劫持请求并返回内存中的文件。 - Wen
在您的生产环境中,您将使用 webpack -p 来构建您的资产,并且您的资产应该由您的应用服务器或 Nginx 服务器提供,而不是由 webpack 服务器或 webpack 中间件提供。因此,在生产环境中,这个配置已经不再有用了,我说得对吗? - Sean
7
不,这个选项在开发服务器中很有用,但它的目的是为了在生产环境中异步加载脚本包。比如你有一个非常大的单页应用程序(比如 Facebook),Facebook 不会希望每次加载主页时都提供所有的 JavaScript 代码,所以它只提供主页所需的部分。当你访问自己的个人资料页面时,它会使用 ajax 加载一些更多的 JavaScript 代码。这个选项告诉它从服务器的哪个位置加载那个脚本包。 - Charlie Martin
@CharlieMartin 你是对的,感谢指正,我已经更新了答案。 - Sean
显示剩余2条评论

36

filename指定了所有打包完毕的代码都会被累加到这个文件中name of file

path指定了输出目录,在该目录下将保存app.js(即filename)文件到磁盘中。如果不存在output directory,webpack会为您创建该目录。 例如:

module.exports = {
  output: {
    path: path.resolve("./examples/dist"),
    filename: "app.js"
  } 
}

这将创建一个名为 myproject/examples/dist 的目录,并在该目录下创建 app.js/myproject/examples/dist/app.js。构建完成后,您可以浏览到 myproject/examples/dist/app.js 查看打包后的代码。

publicPath: “我应该在这里放什么?”

publicPath 指定了Web服务器上从哪个虚拟目录中服务打包后的文件,即 app.js。请注意,使用 publicPath 时的“服务器”可以是 webpack-dev-server 或 express 服务器或您可以与 Webpack 一起使用的其它服务器。

例如:

module.exports = {
  output: {
    path: path.resolve("./examples/dist"),
    filename: "app.js",
    publicPath: path.resolve("/public/assets/js")   
  } 
}

这个配置告诉Webpack将所有的js文件打包到examples/dist/app.js中,并将其写入该文件。

publicPath告诉Webpack-dev-server或Express服务器在server中指定的虚拟位置/ public / assets / js中提供此捆绑文件,也就是说,您必须在html文件中引用该文件:

<script src="public/assets/js/app.js"></script>

总之,publicPath 就像是你的服务器上虚拟目录与 output.path 配置所指定的输出目录之间的映射。每当请求文件 public/assets/js/app.js 时,将会提供 /examples/dist/app.js 文件。


23

你可以使用 publicPath 选项指向 webpack-dev-server 服务“虚拟”文件的位置。 publicPath 选项将与 webpack-dev-server 的 content-build 选项相同。 webpack-dev-server 在启动时会创建虚拟文件,这些虚拟文件类似于 webpack 创建的实际打包文件。基本上,你需要使用 --content-base 选项指向 index.html 所在目录。以下是一个示例设置:

//application directory structure
/app/
/build/
/build/index.html
/webpack.config.js


//webpack.config.js
var path = require("path");
module.exports = {
...
  output: {
    path: path.resolve(__dirname, "build"),
    publicPath: "/assets/",
    filename: "bundle.js"
  }
};  


//index.html
<!DOCTYPE>
<html>
...
<script src="assets/bundle.js"></script>
</html>

//starting a webpack-dev-server from the command line
$ webpack-dev-server --content-base build 

webpack-dev-server已经创建了一个虚拟的资源文件夹,以及一个指向它的虚拟bundle.js文件。您可以通过访问localhost:8080/assets/bundle.js测试此功能,然后检查应用程序中是否存在这些文件。它们只在运行webpack-dev-server时生成。


这是一个很好的解释,但是如果我要将其移至生产环境或手动构建 /build/bundle.js,那么我需要更改 index.html 文件中的 src,对吗? - ArchNoob
抱歉回复晚了。您无需更改源代码。无论您是在生产环境还是开发环境中,Webpack都会在输出路径中创建一个bundle.js文件。在上面的示例中,它将位于/build/bundle.js。 - Isaac Pak
谢谢,我想问一下index.html文件中的src行。现在它指向"assets/bundle.js",如果转移到生产环境,捆绑包将在"build/bundle.js"中,所以我需要在html src行中更改为src="build/bundle.js"。或者有更自动化的方法吗? - ArchNoob
2
我现在明白你的问题了。是的,你需要将src更改为build/bundle.js以进行生产。至于自动化完成此操作的方法,我不确定。我看到其他人创建了两个不同的webpack.config.js文件,一个用于生产,一个用于开发。可能有一种编程方式,比如if(ENV === production) do this...但我没有尝试过。 - Isaac Pak
@ArchNoob 我想向你报告一下我现在在生产环境中的做法。我没有改变 src 的值,而是将 publicPath 的值从 /assets/ 更改为 /build。这样我就不必更改我的 index.html 文件了。我还将 index.html 文件从构建文件夹移动到应用程序的根目录中。 - Isaac Pak
不错的技巧,最近我发现了html-webpack-plugin。也许你也应该去看看它...它很棒! - ArchNoob

18

在我的情况下,我有一个CDN,我打算把所有处理过的静态文件(js、imgs、fonts...)放入我的CDN中,假设URL是http://my.cdn.com/

所以,如果有一个JS文件,在HTML中的原始引用URL是'./js/my.js',则在生产环境中,它应该变为http://my.cdn.com/js/my.js

在这种情况下,我需要做的就是将publicpath设置为http://my.cdn.com/,webpack会自动添加该前缀。


在我的情况下,似乎没有添加任何前缀。 - Param Singh

5

这里有很多好的答案,我将着重介绍output.publicPath: 'auto'

假设您构建项目时会得到以下文件夹结构:

dist/blog/index.html
dist/app.js
dist/app.css
dist/index.html

在这种情况下,我们的两个index.html文件都必须有正确的路径到我们的app.js和app.css (接下来是assets)。让我们考虑以下场景:
  • publicPath: ''或者publicPath: '/':

    当托管在服务器上时,两者都指向网站的根目录(例如https://localhost:8080/),所以一切正常。

    但是,如果您尝试本地打开它们,blog/index.html将没有正确的路径到资源文件。在publicPath: ''的情况下,资源文件将在blog/文件夹中搜索,因为相对路径指向那里。而index.html仍然有正确的路径到资源文件。

    而在publicPath: '/'的情况下,/指向文件系统的根目录,所以我们的两个index.html文件都没有正确的路径到资源文件。

  • publicPath: 'auto':

    在这种情况下,我们的两个index.html文件将具有相对路径到资源文件。所以,blog/index.html将指向../app.css,而index.html将指向app.css


4

2

publicPath在webpack中用于替换CSS中定义的相对路径,以引用图像和字体文件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接