As vue-CLI and other scaffolding tools become more integrated with WebPack, it’s hard to realize how much configuration and optimization you’ve done for packaging when your project is done. Based on the current situation, I tried the packaging configuration by myself. In this process, I did encounter some problems that I was not clear about. Personally, I think the Chinese translation on webpack website is obscure in some places, which may be due to my limited level and understanding.

PublicPath, output.path, devServer.publicPath, devServer.contentBase. This is because these configuration items, if used incorrectly, often result in a 404 condition when requesting the resource.

devServer

One thing to mention is that webpack-dev-server is not written to any output files after compilation. Instead, you keep the bundle files in memory and then serve them to the server as if they were real files mounted on the server root path. If your page wants to find the bundle files in a different path, you can modify this with the publicPath option in the devServer configuration. (Note: serve, the resource as the server’s accessible file)

devServer.publicPath

As the name implies, devServer’s various configurations are only valid in Development mode. The default publicPath is /, so assuming the server is running at http://localhost:8080 and output.filename is set to bundle.js, We can use http://localhost:8080/bundle.js to access the bundle files.

You can also modify devServer.publicPath to place the bundle in the specified directory:

module.exports = {
  // ...
  devServer: {
    publicPath: '/assets/'}}Copy the code

Can now be accessed through http://localhost:8080/assets/bundle.js bundle.

Make sure devServer.publicPath always starts and ends with a slash /.

Webpack-dev-server can be thought of as a server whose main job is to receive browser requests and return resources. When the service starts, webPack is first used to pack the modules and prepare the resources. When Webpack-dev-server receives a resource request from the browser, it first verifies the URL address. If the address is a resource service address (publicPath configured above), the resource is looked for in the webpack result and returned to the browser. Conversely, if the requested address does not belong to the resource service address, the source file is read directly from the hard disk and returned.

Let’s do a simple test for the above:

The configuration file is as follows:

The project directory structure is as follows:

Visit http://localhost:8081/girl.jpeg in the browser, because the address is not a publicPath configuration resource service address, and so directly read hard drive back to the source files.

To sum up: It should be clear what the publicPath field means, which is the path to the build file that can be accessed in the browser.

devServer.contentBase

ContentBase tells the server which directory to serve content from, only if you want to serve static files.

This is the directory where index. HTML is located. If this is not specified, it defaults to the project root directory.

Let’s verify:

Browser access:http://localhost:8081, as shown below:

We change contentBase to contentBase: Path.join (__dirname, ‘public’), proceed to http://localhost:8081 and display the following (favicon.ico and girl.jpeg are in the project public directory) :

output

output.publicPath

Output also has a publicPath attribute. Devserver. publicPath . If the answer is yes, devServer publicPath no value, then development server will try to read the output. The publicPath value, if the output publicPath explicitly set the use value is the value, If no value is set, use the default devServer.publicPath /.

PublicPath: /assets/? / devServer.publicPath: /assets/

Next, set different values for both, such as devServer.publicPath: /path/

However, these two different values can cause other problems:

Browser access is http://localhost:8081/path/index.html, but the script tag reference resource file prefix is assets, that is to say to the output. The publicPath value shall prevail.

In fact, publicPath is a very important configuration item and is easily confused with Path. Functionally, path is used to specify the output location of the resource, while publicPath is used to specify the request location of the resource.

  • Output location: The directory generated by the packaged resource, typically designated as the dist directory in the project.

  • Request location: The indirect resource path requested by JS or CSS. Resources in the page are divided into two types, one is directly requested by THE HTML page, such as JS loaded by script tag; The other is requested by JS or CSS, such as asynchronously loaded JS, image fonts requested from CSS, etc. PublicPath is used to specify where these indirect resources are requested.

PublicPath has three forms, which are described as follows:

  1. The HTML related

    HTML related, which means we can specify publicPath as a relative path to HTML. When these resources are requested, the HTML path of the current page plus the relative path constitute the actual REQUEST URL. Such as:

    / / assume that the current HTML address to https://example.com/app/index.html
    // The name of the asynchronously loaded resource is 0.chunk.js
    publicPath: ' ' https://example.com/app/0.chunk.js / / the actual path
    publicPath: './js' / / the actual path to https://example.com/app/js/0.chunk.js
    publicPath: '.. /assets/' / / the actual path to https://example.com/assets/0.chunk.js
    Copy the code
  2. The Host related

    If publicPath starts with /, it indicates that publicPath is based on the host name of the current page. Such as:

    / / assume that the current HTML address to https://example.com/app/index.html
    // The name of the asynchronously loaded resource is 0.chunk.js
    publicPath: '/' https://example.com/0.chunk.js / / the actual path
    publicPath: '/js/' / / the actual path to https://example.com/js/0.chunk.js
    publicPath: '/dist/' / / the actual path to https://example.com/dist/0.chunk.js
    Copy the code
  3. CDN related

    The preceding two configurations are relative paths. You can configure publicPath as an absolute path. This situation generally occurs when static resources are placed on the CDN. Because their domain name is inconsistent with the current page domain name, they need to be specified in the form of an absolute path. When publicPath starts as a protocol header or relative protocol, it indicates that the current path is CDN-related. Such as:

    / / assume that the current HTML address to https://example.com/app/index.html
    // The name of the asynchronously loaded resource is 0.chunk.js
    publicPath: 'http://cdn.com/' http://cdn.com/0.chunk.js / / the actual path
    publicPath: 'https://cdn.com/' / / the actual path to https://cdn.com/0.chunk.js
    publicPath: '//cdn.com/assets/' / / the actual path is / / cdn.com/assets/0.chunk.js
    Copy the code

output.path

Path specifies the output location of the resource. The value must be an absolute path. Such as:

const path = require('path');
module.exports = {
  entry: './src/app.js'.output: {
    filename: 'bundle.js'.path: path.join(__dirname, 'dist')}}Copy the code

The above configuration outputs resources to the dist directory of the project. In versions prior to WebPack V4, packaged resources are generated in the project root by default, so we need this configuration; After WebPack V4, output.path defaults to the dist directory, so we don’t have to configure it separately unless we need to change it.

In combination with devServer.publicPath (specifying the static resource service path for webpack-dev-server), let’s look at the following example:

const path = require('path');
module.exports = {
  entry: './src/app.js'.output: {
    filename: 'bundle.js'.path: path.join(__dirname, 'dist')},devServer: {
    publicPath: '/assets/'.port: 3000}}Copy the code

As you can see from the webpack configuration, output.path is the dist directory, so bundle.js should be generated in the dist directory. But when we start webpack dev – server services, access to localhost: 3000 / dist/bundle. Js but will get 404. . This is because the devServer publicPath the resource location points to the localhost: 3000 / assets /, so only access localhost: 3000 / assets/bundle. Js to get the results we want.

To avoid confusion, we can keep the publicPath of webpack-dev-server consistent with output.path in webpack, so that the output directory of resources in any environment is the same. Take a look at the following example:

const path = require('path');
module.exports = {
  entry: './src/app.js'.output: {
    filename: 'bundle.js'.path: path.join(__dirname, 'dist')},devServer: {
    publicPath: '/dist/'.port: 3000}}Copy the code

The configuration above can guarantee access localhost: 3000 / dist/bundle. Js to get the desired results.

This article is part of the “Gold Nuggets For Free!” Activity, click to viewEvent details

Reference: Webpack Chinese