Webpack builds a local development server


This prior webpack configuration is essential. However, the development experience is not good, and npm run build has been required to package manually.

We hope that when the file changes, the compilation and display can be automatically completed;
in order to complete the automatic compilation, webpack provides several optional methods:

  • webpack watch mode;
  • webpack-dev-server (commonly used);
  • webpack-dev-middleware;

Webpack watch

webpack provides us with watch mode.
In this mode, all files in the webpack dependency graph, as long as one of them is updated, the code will be recompiled;
we don't need to manually run the npm run build command.
Note: It will only be automatically compiled and packaged. To view it in real time in the browser, you must cooperate with the live-server to open the html.

How to turn on the watch? Two ways:

  • Method 1: In the exported configuration file, that is, add in webpack.config.jswatch: true;
  • Method 2: In the command to start webpack, add --watchthe logo;

We can add flags to npm scripts, because the scripts in scripts actually use npm run to help you execute the following commands on the command line. The same is true for webpack here. Execution on the command line essentially depends on webpack-cli, including --watch attribute configuration is also added to the configuration file by cli.

{
    
    
  "scripts": {
    
    
    "build": "webpack --watch"
  },
}

webpack-dev-server

If we want to implement live reloading (real-time reloading) without using live-server, we can use webpack-dev-server.
It will start an express server, so when the browser opens, it will download index.html first, and then download other files from index.html, just like opening a general website.

In fact webpack-dev-server does not write any output files after compilation. Instead keep the bundle file in memory

Install:npm i webpack-dev-server -D

Use: webpack servejust start it, usually we also use it in the npm script
"serve": "webpack serve --config webpack.config.js"
! paste&height=142&id=u3e7b03df&name=image.png&originHeight=222&originWidth=1055&originalType=binary&ratio=1&rotation=0&showTitle=false&size=42403&status=error&style=none&taskId=ud0771a41-16ac -4b79-bfad-aaff037763f&title=&width=675.2)

The path where the webpack-dev-server service looks for files is:

  • http://[devServer.host]:[devServer.port]/[output.publicPath]/[output.filename]
output: {
    
    
  filename: "js/bundle.js",
  path: path.resolve(__dirname, "./dist"),
  publicPath: "hhh"
}

The default host and port are localhost:8080. If the output is configured as above, the url for requesting js is

  • http://127.0.0.1:8080/hhh/js/bundle.js

webpack configuration: devServer

If we want to configure the local development server, we can devServerconfigure it in the top-level options of the wepback configuration object. Of course, many of them are already configured by default.

In addition, a top-level option target can be added to identify the packaged product usage environment.target: "web"|"node"

static

Many properties can be configured in devServer, contentBase is one of them.
contentBase: Indicates that the dev server will tell the browser which directory the files that are not packaged by webpack are located, so that the browser can directly go to that directory to obtain the files instead of downloading them in the packaged package.
For example, favorite.ico, the production environment must be copied to the packaged folder, but the development stage does not need to be copied, so you can specify ./public as contentBase to facilitate the browser to load the icon.
Some extra files are very large, so they do not need to be packaged, which improves the efficiency of development and packaging.
However it has been deprecated.
image.png
All the options that can be configured by devServer have been marked in the prompt information, and of course many options have default configurations.

Now if you want to achieve the same effect as above contentBase, you need to use staticoptions to specify the static file directory. The files in the directory are equivalent to being added to the packaged export directory.

module.exports = {
    
    
  devServer: {
    
    
    static: "./img"
  }
}
<img src="./1.png" alt="">

Open the browser to view, and you will find that picture 1.png is linked to the local img folder, and has not been packaged.
image.png

host

host sets the host address:

  • The default value is localhost;
  • If you want to be accessible from other places, you can set it to 0.0.0.0;

The difference between localhost and 0.0.0.0:

  • localhost: essentially a domain name, usually resolved to 127.0.0.1;
  • 127.0.0.1: Loop Back Address (Loop Back Address), which means that the packets sent by our host are directly received by ourselves;

The normal database packet sending path is the application layer-transport layer-network layer-data link layer-physical layer; the
loopback address is obtained directly at the network layer, and will not go to the data link layer and physical layer;
So even if someone else starts the local server in the host under the same network segment, we cannot access other people's server through 127.0.0.1. Because the request will not be sent out by the network card at all, this is why 127.0.0.1 is called the local host.

0.0.0.0: Listen to all addresses on IPV4, and then find different applications according to the port;
for example, if we open the service of 0.0.0.0, in the hosts under the same network segment, others can access my server through 0.0.0.0 . Because it is a broadcast address, the request will be sent to all hosts under the network segment.

port、open、compress

port: set the listening port, the default is 8080
open: whether to open the browser:

  • The default value is false, setting it to true will open the browser;
  • It can also be set to a value similar to Google Chrome;

compress Whether to enable gzip compression for static files:

Note: Some ports are in the blacklist of the browser, for example: 6666. These ports cannot be set.

Hot Module Replacement (HMR)

What is HMR?

  • The full name of HMR is Hot Module Replacement, translated as module hot replacement;
  • Module hot replacement refers to replacing, adding, and deleting modules during the running of the application without refreshing the entire page ;

HMR improves the speed of development through the following methods:

  • Don't reload the whole page, which can keep some application state from being lost;
  • Only update the content that needs to be changed, saving development time;
  • If you modify the source code of css and js, it will be updated in the browser immediately, which is equivalent to directly modifying the style in the devtools of the browser;

How to use HMR?
By default, webpack-dev-server already supports HMR, and it is turned on by default;**devServer: { hot: true }**
if HMR is not turned on, when we modify the source code, the entire page will be automatically refreshed, using live reloading;

image.png
WDS :webpack Dev Server

But you will find that when we modify the code of a certain module, the entire page is still refreshed:
this is because we need to specify which modules are updated to perform HMR;

if (module.hot) {
    
    
  module.hot.accept("./js/element.js", () => {
    
    
    console.log("element模块发生更新了");
  })
}

Framework HMR

There is a question: When developing other projects, do we often need to manually write module.hot.accpet related APIs?
For example, in the development of Vue and React projects, we have modified the components and hope to perform hot updates. How should we operate at this time?

In fact, the community already has very mature solutions for these:
for example, in vue development, we use vue-loader, which supports the HMR of vue components and provides an out-of-the-box experience; for example,
in react development, there is React Hot Loader , adjust react components in real time (currently React has been officially deprecated, use react-refresh instead)

Principle of HMR

So what is the principle of HMR? How can it be possible to only update the content in one module?

  • webpack-dev-server will create two services: a service that provides static resources (express) and a Socket service (net.Socket);
  • The express server is responsible for directly providing static resource services (packaged resources are directly requested and parsed by the browser);

HMR Socket Server is a long socket connection:

  • One of the best benefits of a long connection is that the two parties can communicate after the connection is established (the server can directly send files to the client);
  • When the server detects that the corresponding module changes, two files, .json (manifest file) and .js file (update chunk), will be generated;
  • Through the long connection, these two files can be directly sent to the client (browser);
  • After the browser gets the two new files, it loads the two files through the HMR runtime mechanism, and updates the modified modules;

Proxy

Proxy is a very common configuration option in our development. Its purpose is to set up a proxy to solve the problem of cross-domain access:

  • For example, one of our API requests is http://192.163.0.66/12345, but the domain name of the local startup server is http://localhost:8080. At this time, sending network requests will cause cross-domain problems;
  • Then we can send the request to a proxy server first. The proxy server and the API server have no cross-domain problems, so we can solve our cross-domain problems.
  • The proxy server started by webpack is express

cross domain

basic use

Set a placeholder in devServer that replaces the requested target server address .
For example, the service source started by the local webpack is http://localhost/8080, and now you want to request the target source http://192.163.0.66:12345, the api is /get.

fetch("http://192.163.0.66:12345")
  .then(response => response.json())
  .then(result => console.log(result))

Obviously this must happen across domains, because the port numbers are different. At this time, we need to use a proxy. The specific method is to let the placeholder replace the target source:

fetch("/api/get") // ‘/api’ 为占位符
	.then(response => response.json())
  .then(result => console.log(result))

But now there is a problem, we still can't request the data. Because the placeholder will not be deleted, it will be added to the url that actually requests the server data.
webpack devServer proxy.png

pathRewrite

The current request architecture is, browser request --> proxy server request --> real server.
We check the request header url, and there has been http://localhost/8080/api/getno cross-domain, but the request sent by the proxy server to the real server also has a placeholder/api, but in fact there is no corresponding resource on the real server, so it will return 404 .
At this time, it is absolutely necessary to rewrite the request url of the proxy server and delete the placeholder. ****pathRewrite: { "^/api-hy": "" }**

changeOrigin

changeOrigin can modify the host attribute in the headers in the proxy request, and change it to the target request source corresponding to the target.
The proxy server sends a request to the real server, because the server does not have a same-origin policy, so any request source can send it at will. For example, the proxy server started by webpack is the source of the request to the real server http://localhost:3000.
However, there may be restrictions on the real server, such as preventing crawlers and the like. The url of the verification request header must be consistent with the source of the real server. Then you can set changeOrigin to true to modify. As shown in the above figure.

General configuration

Summary:

  • target: Indicates the target address to be proxied to,
  • pathRewrite: path rewrite.
  • secure: By default, the server that forwards to https is not received, if you want to support it, you can set it to false;
  • changeOrigin: It indicates whether to update the host address in the headers requested by the proxy;
devServer: {
    
    
    proxy: {
    
    
      "/api-hy": {
    
     // 占位符
        target: "http://192.163.0.66/12345",
        pathRewrite: {
    
    
          "^/api-hy": ""
      	},
        secure: false,
        changeOrigin: true
      }
    }
  }
}

historyApiFallback


historyApiFallback is a very common attribute in development. Its main function is to solve the error of returning 404 when the SPA page refreshes the page after the route jumps .
Because refreshing is to send a request to the server with the url on the address bar, but the current route is set in the front end of the SPA page, and the resource corresponding to the url of the server will be 404.

historyApiFallback has two values:

  • boolean value: default is false

If it is set to true, the content of index.html will be automatically returned when a 404 error is returned during refresh;

  • The value of object type can configure the rewrites attribute:

You can configure from to match the path and decide which page to jump to;

In fact, the historyApiFallback function in devServer is implemented through the connect-history-api-fallback library:
you can view the connect-history-api-fallback document

Guess you like

Origin blog.csdn.net/qq_43220213/article/details/129608113