What does "publicPath" in Webpack do?
Asked Answered
H

9

310

Webpack docs state that output.publicPath is:

The output.path from the view of the JavaScript.

Could you please elaborate on what this actually means?

I use output.path and output.filename to specify where Webpack should output the result, but I’m not sure what to put in output.publicPath and whether it is required.

module.exports = {
  output: {
    path: path.resolve("./examples/dist"),
    filename: "app.js",
    publicPath: "What should I put here?"   
  } 
}
Herbage answered 4/3, 2015 at 4:46 Comment(3)
I'd like to add to this question: when would you use path and when would you use publicPath?Amish
Answer is here: github.com/webpack/docs/wiki/configuration#outputpublicpathProhibit
If helps: tomasalabes.me/blog/_site/web-development/2016/12/10/…Susan
P
187

output.path

Local disk directory to store all your output files (Absolute path).

Example: path.join(__dirname, "build/")

Webpack will output everything into localdisk/path-to-your-project/build/


output.publicPath

Where your browser can access uploaded bundled files. (absolute path, or relative to main HTML file)

Example: /assets/

Assumed you deployed the app at server root http://server/.

By using /assets/, the app will find webpack assets at: http://server/assets/. Under the hood, every urls that webpack encounters will be re-written to begin with "/assets/".

src="picture.jpg" Re-writes ➡ src="/assets/picture.jpg"

Accessed by: (http://server/assets/picture.jpg)


src="/img/picture.jpg" Re-writes ➡ src="/assets/img/picture.jpg"

Accessed by: (http://server/assets/img/picture.jpg)

Poundal answered 3/8, 2016 at 15:57 Comment(1)
output.publicPath has an 'auto' option.—But what is it doing except burning extra CPU cycles for the same effect as plain '' or './' have. No clue. Who knows that?Standifer
D
76

When executed in the browser, webpack needs to know where you'll host the generated bundle. Thus it is able to request additional chunks (when using code splitting) or referenced files loaded via the file-loader or url-loader respectively.

For example: If you configure your http server to host the generated bundle under /assets/ you should write: publicPath: "/assets/"

Dorso answered 6/3, 2015 at 13:10 Comment(1)
Can you please tell me where is the assets folder located? I would like to see the files inside assets folder Thanks.Luckett
N
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 file under src folder, and you config your webpack to build the source file to dist folder with output.path.

But you want to serve your static assets under a more meaningful location like webroot/public/assets, this time you can use out.publicPath='/webroot/public/assets', so that in your html, you can reference your js with <script src="/webroot/public/assets/bundle.js"></script>.

when you request webroot/public/assets/bundle.js the webpack-dev-server will find the js under the dist folder

Update:

thanks for Charlie Martin to correct my answer

original: the publicPath is just used for dev purpose, this is not just for dev purpose

No, this option is useful in the dev server, but its intention is for asynchronously loading script bundles in production. Say you have a very large single page application (for example Facebook). Facebook wouldn't want to serve all of its javascript every time you load the homepage, so it serves only whats needed on the homepage. Then, when you go to your profile, it loads some more javascript for that page with ajax. This option tells it where on your server to load that bundle from

Ninefold answered 30/8, 2015 at 6:50 Comment(7)
It's not just for dev purpose, @jhnns's answer explains how it affects loader outputs.Varicotomy
it's the same isn't it? this property tells your loader, and your middleware where to find the real assets, hopfully you will not use webpackmiddleware , or webpack-dev-server in your production enviroment, so I think this is just for dev enviroment, please refer to webpack.github.io/docs/webpack-dev-server.htmlNinefold
From this webpack.github.io/docs/configuration.html#output-publicpath it seems this option tells webpack to fill in the correct url or path of assets in the generated files, not just for middlewares. When running dev server, I think the middleware looks at publichPath to hijack requests and return the in-memory files.Varicotomy
exactly, in your production enviroment, your will use webpack -p to build your assets, and your assets should be served by your application server or your nginx server instead of webpack server or webpack middleware, so this config no longer useful at production enviroment, am I right?Ninefold
No, this option is useful in the dev server, but its intention is for asynchronously loading script bundles in production. Say you have a very large single page application (for example Facebook). Facebook wouldn't want to serve all of its javascript every time you load the homepage, so it serves only whats needed on the homepage. Then, when you go to your profile, it loads some more javascript for that page with ajax. This option tells it where on your server to load that bundle fromFurbish
Checkout Section 9 on Asynchronous loading for an example... github.com/petehunt/webpack-howtoFurbish
@CharlieMartin you are right, thanks for correct me, I have update the answerNinefold
M
36

filename specifies the name of file into which all your bundled code is going to get accumulated after going through build step.

path specifies the output directory where the app.js(filename) is going to get saved in the disk. If there is no output directory, webpack is going to create that directory for you. for example:

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

This will create a directory myproject/examples/dist and under that directory it creates app.js, /myproject/examples/dist/app.js. After building, you can browse to myproject/examples/dist/app.js to see the bundled code

publicPath: "What should I put here?"

publicPath specifies the virtual directory in web server from where bundled file, app.js is going to get served up from. Keep in mind, the word server when using publicPath can be either webpack-dev-server or express server or other server that you can use with webpack.

for example

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

this configuration tells webpack to bundle all your js files into examples/dist/app.js and write into that file.

publicPath tells webpack-dev-server or express server to serve this bundled file ie examples/dist/app.js from specified virtual location in server ie /public/assets/js. So in your html file, you have to reference this file as

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

So in summary, publicPath is like mapping between virtual directory in your server and output directory specified by output.path configuration, Whenever request for file public/assets/js/app.js comes, /examples/dist/app.js file will be served

Monotony answered 14/8, 2019 at 9:8 Comment(0)
S
23

You can use publicPath to point to the location where you want webpack-dev-server to serve its "virtual" files. The publicPath option will be the same location of the content-build option for webpack-dev-server. webpack-dev-server creates virtual files that it will use when you start it. These virtual files resemble the actual bundled files webpack creates. Basically you will want the --content-base option to point to the directory your index.html is in. Here is an example setup:

//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 has created a virtual assets folder along with a virtual bundle.js file that it refers to. You can test this by going to localhost:8080/assets/bundle.js then check in your application for these files. They are only generated when you run the webpack-dev-server.

Stringent answered 4/1, 2017 at 23:45 Comment(6)
Such a good explanation, but then if i move to production or make the build by hand /build/bundle.js I will have to change the src in my index.html file right?Fewness
Sorry for the late response. You do not have to change the src. Whether your in production or development, webpack will create a bundle.js in the output path. In the above example it will be /build/bundle.js.Stringent
Thank you, I'm asking about the src line in index.html file. Right now it's pointing to "assets/bundle.js" if it move to production the bundle is going to be in "build/bundle.js" so i'll have to change that in the html src line to src="build/bundle.js". Or is there a more automated way?Fewness
I understand your question now. Yes you will need to change the src to build/bundle.js for production. As for an automated way to do this, I am not sure of. I have seen others create 2 different webpack.config.js files, one for production and one for development. There is probably a way prgrammatically like if(ENV === production) do this... but I haven't tried that.Stringent
@Fewness Just a heads up on how I doing this in production now. I did not change the src value but instead i changed my publicPath value from /assets/ to /build. This way I don't have to change my index.html. I also moved my index.html out of the build folder and into the root of the application.Stringent
Nice trick, I recently found out about html-webpack-plugin. Maybe you should check it out too.. It's pretty neat!Fewness
S
18

in my case, i have a cdn,and i am going to place all my processed static files (js,imgs,fonts...) into my cdn,suppose the url is http://my.cdn.com/

so if there is a js file which is the orginal refer url in html is './js/my.js' it should became http://my.cdn.com/js/my.js in production environment

in that case,what i need to do is just set publicpath equals http://my.cdn.com/ and webpack will automatic add that prefix

Squier answered 14/6, 2016 at 8:20 Comment(1)
It doesn't seem to add any prefix in my case.Roily
N
6

There are lots of good answers here, so I'll focus on output.publicPath: 'auto'.

Say when you build your project you get the next folder structure:

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

In this case, both our index.html files have to have a correct path to our app.js and app.css (next - assets). Let's consider the next scenarios:

  • publicPath: '' or publicPath: '/':

    When hosted on a server both point to the root of the website (ex. https://localhost:8080/), so everything works fine.

    But should you try to open them locally, blog/index.html won't have a correct path to the assets. In case of publicPath: '' assets will be searched in the blog/ folder since that's where the relative path is pointing to. index.html still has the correct path to assets.

    And in case of publicPath: '/', / points to the root of the filesystem, so neither of our index.html files will have a correct path to assets.

  • publicPath: 'auto':

    In this case, both our index.html files will have relative paths to the assets. So, blog/index.html will be pointing to ../app.css, and index.html will be pointing to app.css.

New answered 13/6, 2021 at 21:42 Comment(0)
V
4

The webpack2 documentation explains this in a much cleaner way: https://webpack.js.org/guides/public-path/#use-cases

webpack has a highly useful configuration that let you specify the base path for all the assets on your application. It's called publicPath.

Vow answered 5/5, 2017 at 19:35 Comment(0)
B
2

publicPath is used by webpack for the replacing relative path defined in your css for refering image and font file.

Bulley answered 4/1, 2017 at 4:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.