Summary:
-
Introduction + five cores
-
In webpack, everything is a module, and any file can be regarded as a module. js, css and pictures are all modules.
-
loader
-
By default, webpack can only process files in js and json formats, while the role of loader is to convert files in other formats into files that webpack can process.
-
regular expression
-
/\.xxx$/
The above formula represents the file with the suffix xxx;
-
Regular matching rule:
^Represents the starting position of the string
$indicates the end of the string/The / / in. xxx $/ represents the built-in of the regular expression.
-
-
-
General process
- Initialize a project with npm init and install webpack
- Copy the three previously created files into the project
- On the command line, enter webpack index.js
- Change the index.js file introduced in index.html to. / dist/main.js file and run it in the browser
- If you do not want the code to be compressed, you can add -- mode development after the command to indicate that it is packaged in the development mode (the development mode will not compress the code)
- When webpack is packaged, the webpack.config.js file in the project root directory will be used as the configuration file by default. Therefore, you can change the default configuration of webpack by creating a new webpack.config.js file
-
Function and difference of - S -D during npm installation
-
-S
-
Namely--save((save) The package name will be registered in package.json of dependencies In the production environment, the dependency of this package still exists
-
-
-D
-
Namely--dev((production) The package name will be registered in package.json of devDependencies Inside, the package exists only in the development environment-D,as babel,sass-loader These parsers
They are different from dependencies because they only need to be installed on the development machine and do not need to run code in the production environment
-
-
-
Plug in
- CleanWebpackPlugin: automatically clear the old files every time you pack. The output.path directory is cleared by default
- html webpack plugin: generates an html file and automatically introduces the packaged js file
- MiniCssExtractPlugin: extract css into a separate file and import it through link
- Optimize cssassets webpack plugin: in order to reduce the file volume, we usually compress the css file
-
The loader handles the style file css in the project
- webpack cannot process css files by default, so you need to use css loader to process css files in the project. Create a new css file and import it in js. You must import it in js (not in html)
- The loader needs to be configured in the module.rules of the webpack configuration file
- step
- Install CSS loader and add configuration in the configuration file
- Install style loader and continue to modify the configuration
- The function of style loader is to insert css into the style tag in the head
- Execute the package command and open the index.html file in the browser
-
The loader processes the photos in the project
- file-loader
- Only bg.jpeg introduced by css is packaged and output, and the imported image path is replaced by the packaged path. There are problems with the images directly introduced by js and html
- For images dynamically added through js, we can use the require() method to introduce
- Modify the file loader parameter (solve the problem of js importing pictures)
- html-loader
- For images in html, we can use html loader or html withimg loader
- Therefore, when there is ejs syntax in html, we can't use html loader to process images, but directly use ejs syntax to introduce
- deploy
- So far, all our files are exported to dist directory, which is not convenient for later release and launch
- For example, css files are output to the style directory, pictures are output to the images directory, js is output to the js Directory
- Modify the webpack configuration and repackage
- url-loader
- Use URL loader instead of file loader. URL loader will encode and package small images into files based on 64 to reduce the number of network requests
- image-webpack-loader
- Compress pictures
- file-loader
1, Basic concepts
1. What is webpackWebpack is a modular packaging tool. It performs static analysis according to the dependencies of modules, and then generates corresponding static resources according to the specified rules
2. Understand module, chunk and bundleIn webpack, everything is a module, and any file can be regarded as a module. js, css and pictures are all modules.
webpack will introduce the entry file and its dependencies into a chunk, and then package it into a bundle after a series of processing.
(1) entry
The entry of webpack package. Its value can be string, array or an object
// Single entry single file entry: "./src/index.js" // Single entry multi file entry: ["./ src/index.js", "./src/common.js"] // If index.js and common.js have no dependency, they can be packaged together in this way // Multiple entry entry: { page1: "./src/page1.js", //page1 and page2 are key values page2: "./src/page2.js" }
(2) output
The output packaged by webpack is commonly configured as follows
output: { path: path.resolve(__dirname, "./dist"), // Single entry (default) // filename: "main.js", // Filename: "JS / main. JS" // In case of multiple entries, the file name cannot be written dead because there will be multiple outputs filename: "[name].js", // Name indicates the name of the chunk. Here is the key value in the entry chunkFilename: "[name].js", // The packaged name of the module loaded on demand publicPath: "/" // The path where the project is deployed on the server. If it is in the root path, otherwise/ }
(3) mode
webpack packaging is divided into two modes: development mode and production mode. The default mode is production mode
(4) loader
By default, webpack can only process files in js and json formats, while the role of loader is to convert files in other formats into files that webpack can process
The loader needs to be configured in the module.rules of the webpack configuration file
module.exports = { entry: ..., output: ..., module: { noParse: /node_modules/, //Ignore resolving node_ Files in modules rules: [ { test: /\.xxx$/, // Match the file with suffix xxx; Regular matching rule: ^ indicates the starting position of the string //$represents the end position of the string, and / / in / \. xxx $/ represents the inherent position of the regular expression // Single loader // loader: "xxx-loader", // options: {}, // Multiple loaders. The processing order of loaders is from back to front, so the loaders that need priority processing are placed at the end of the array // use: ["xxxx-loader", "xxx-loader"], // If a loader needs to be configured, write it in the following format use: [ { loader: "xxxx-loader", options: {} }, "xxx-loader" ], include: [path.resolve(__dirname, "./src")], // Only parse the files in src, which can be regular files exclude: [path.resolve(__dirname, "./library")], // Ignore the files in the library, which can be regular // When multiple rules match a certain type of file at the same time, you can use the enforce parameter to specify the priority enforce: "pre" // The loader in the rule is executed first, and the loader in the rule is executed last }, { // When the rules match, the following rules are no longer matched. For example, if a file matches the first rule, it will no longer match the following rule oneOf: [ { test: /\.xxx$/, use: "xxx-loader" }, { test: /\.xxx$/, use: "xxx-loader" } ] } ] } }
(5) plugin
webpack plug-ins. Each plug-in has a specific function, which can handle things that the loader cannot handle
The use of plug-ins is very simple. Just add the instantiation object of the plug-in in the plugins array
const xxxWebpackPlugin = require("xxx-webpack-plugin"); module.exports = { entry: ..., output: ..., plugins: [ new xxxWebpackPlugin(), new xxxxWebpackPlugin({ // Configuration items for plug-ins }) ] }
2, Simple use of webpack
- Create util.js, index.js, index.html, and write the following
// util.js export const print = (str) => { console.log(str); }; // index.js import from "./util"; print("hello webpack"); // index.html ... <!-- stay body Introduced in index.js --> <body> <script src="./index.js"></script> </body> ...
- Open index.html in the browser and find an error on the console
Because the browser does not support the modular syntax of es6, webpack can work at this time
-
Initialize a project with npm init and install webpack
NPM I webpack cli - g / / global installation
NPM I webpack cli - D / / installed in the project
4. Copy the three newly created files into the project. The structure is as follows:
- On the command line, enter webpack index.js
index.js indicates the entry file. Since the default output of webpack is dist/main.js, there is no need to specify the exit. You can also use webpack entry -o output to specify the exit
After executing the command, you will find that a dist folder and the main.js file are generated on the left
- Change the index.js file introduced in index.html to. / dist/main.js file and run it in the browser
It runs successfully without error
When you open main.js, you will find that the code in it has been compressed. If you don't want the code to be compressed, you can add -- mode development after the command to indicate that it is packaged in the development mode (the development mode will not compress the code)
Use profileIt is very cumbersome to enter a long string of commands during each package. You can add scripts in package.json, as shown in the following figure
Then it is packaged by npm run build:dev or npm run build:pro (build:dev and build:pro are user-defined names)
When webpack is packaged, the webpack.config.js file in the project root directory will be used as the configuration file by default. Therefore, you can change the default configuration of webpack by creating a new webpack.config.js file
// webpack.config.js module.exports = { //mode: "development", / / because the packaging mode is specified in the package.json script, it does not need to be set entry: "./src/index.js", output: { path: path.resolve(__dirname, "./dist"), filename: "main.js", } }
3, HtmlWebpackPlugin and CleanWebpackPlugin
Copy a copy of index.html to the dist directory, and modify the main.js path it introduces to the correct relative path
Create a new server.js file and add the following code (using the express framework in NodeJS)
const express = require("express"); // Install npm i express -D first const path = require("path"); const app = express(); app.use(express.static(path.resolve(__dirname, "dist"), )) app.listen(3000);
Enter node server.js on the command line, and then open 127.0.0.1:3000 in the browser. The results are as follows
Modify the parameter of the print function in index.js to "hello node", repackage and refresh the page
The print results were not updated because the browser's strong cache took effect and did not request new files. The cache is based on the url. As long as the url changes, the cache will become invalid. We only need to modify the js file name to modify the corresponding url. Therefore, we want the packaged file name to be generated dynamically according to the file content. At this time, we can modify the configuration as
module.exports = { entry: "./src/index.js", output: { path: path.resolve(__dirname, "./dist"), filename: "[chunkhash:10].js", // The hash value of the chunk content, which will be described in detail later } }
Package and refresh the page (remember to modify the js file name introduced in. / dist/index.html)
It can be found that the file name has changed and the cache problem has been successfully solved. However, the change of file name raises two new problems
- You have to manually modify the js file name introduced in html every time you package
- The new file will not overwrite the old file, and there are more and more files in the output directory
HtmlWebpackPlugin and CleanWebpackPlugin can solve these two problems for us
npm i html-webpack-plugin clean-webpack-plugin -D
CleanWebpackPlugin: automatically clear the old files every time you pack. The output.path directory is cleared by default
html webpack plugin: generates an html file and automatically introduces the packaged js file
Add plugins configuration in config
const HtmlWebpackPlugin = require("html-webpack-plugin"); const { CleanWebpackPlugin } = require("clean-webpack-plugin"); module.export = { ... plugins: [ new HtmlWebpackPlugin(), new CleanWebpackPlugin() ] }
The html generated by the final package is shown in the figure below, which automatically helps us introduce js files
The html automatically generated by HtmlWebpackPlugin has no content. If you need to generate according to the existing html, you can specify a template for the plug-in. The common parameters are as follows
module.exports = { // The three entries here are to explain the chunks and excludeChunks of htmlwebpack plugin entry: { page1: "./src/page1.js", page2: "./src/page2.js", common: "./src/common.js" }, plugins: [ new HtmlWebpackPlugin({ filename: "index.html", // The file name of the generated html template: "index.template.html", // Specify template title: "hello webpack", // Set the title of html, which can be introduced in html through ejs syntax inject: true, // By default, the script tag is located at the bottom of the body, and the optional values are body, header and false (indicating that JS is not automatically introduced) hash: false, // true means adding a hash value as a parameter after the imported js file, SRC = "main. js"? 78ccc964740f25e35fca" chunks: [page1, common], // There will be multiple files in multi entry packaging. All files are imported by default. This configuration means that only page1 and common are imported minify: { collapseWhitespace: true, // Remove spaces minifyCSS: true, // Compress html inline css minifyJS: true, // Compress html inline js removeComments: true, // Remove comment } }), // Multiple pages require new multiple objects new HtmlWebpackPlugin({ ... excludeChunk: [page1], // page1 does not need to be introduced, that is, only page2 and page2 are introduced }) ] } // index.html ... <head> <!-- After packaging, it will be replaced with the in the plug-in parameters title — hello webpack --> <title><%= htmlWebpackPlugin.options.title %></title> </head> ...
4, Working with style files in a project
webpack cannot process css files by default, so you need to use css loader to process css files in the project
Create a new css file and import it in js. Be sure to import it in js (no need to import it in html)
// index.css body { background-color: plum; } // index.js ... import "./index.css"
Install CSS loader and add configuration in the configuration file
npm i css-loader -D
module.exports = { ... module: { rules: [ { test: /\.css$/, use: "css-loader" } ] } }
Execute the package command and open the index.html file in the browser
As shown in the figure above, the background color of the page has not changed, and there is no style in html
Although css is packaged in js files, it does not work on the corresponding elements. At this time, it needs to be handled by style loader
Install style loader and continue to modify the configuration to
npm i style-loader -D
module: { rules: [ { test: /\.css$/, use: ["style-loader", "css-loader"] // From back to front, execute CSS loader first, and then style loader } ] }
Repackage and refresh the page. The final effect is shown in the figure below
Therefore, the function of style loader is to insert css into the style tag in the head
In the actual project development, we may need to extract the css into a separate file and introduce it through link, so we can use the MiniCssExtractPlugin plug-in to do this
Install MiniCssExtractPlugin and replace style loader with MiniCssExtractPlugin.loader. Modify the configuration as follows
npm i mini-css-extract-plugin -D
output: { path: path.resolve(__dirname, "./dist"), filename: "[name].js" // For ease of understanding, we change [chunkash: 10]. JS to [name].js, indicating the name of the chunk }, module: { rules: [ { test: /\.css$/, use: [MiniCssExtractPlugin.loader, "css-loader"] } ] }, plugins: [ new MiniCssExtractPlugin(), new CleanWebpackPlugin(), new HtmlWebpackPlugin({ template: "index.html", title: "hello webpack" }) ]
The file and page effects generated after packaging are shown in the figure below
CSS is separately packaged into main.css (because index.css and index.js belong to the same chunk, their chunkname is main), and the generated html file is imported using link (the html webpack plugin helps us do this)
In order to reduce the file size, we usually compress the css file by using the optimizecssassatswebpackplugin plug-in
Install optimizecssasassetswebpackplugin and add
npm i optimize-css-assets-webpack-plugin -D
plugins: [ ... new OptimizeCssAssetsWebpackPlugin() ]
In order to demonstrate the effect, add a little more style in index.css, and then package it. It is found that the content of the output CSS file is compressed to one line
For. Less,. scss and other style files, you only need to install the corresponding loader and add configuration. Take less as an example
{ test: /\.less$/, use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"] }
5, Working with pictures in a project
Like style files, webpack cannot process images by default, so it needs a corresponding loader to process them
Install file loader and add corresponding configuration
npm i file-loader -D
// Add in module.rules { test: /\.(png|jpe?g|gif|svg)$/, use: { loader: "file-loader", options: { name: "[name]-[contenthash:10].[ext]" // ext indicates the suffix of the file } } }
Modify and package the index.html, index.css and index.js files, as shown in the following figure
Preview Results
As can be seen from the above two figures, only bg.jpeg imported from css is packaged and output, and the imported image path is also replaced with the packaged path. There are problems with the images directly imported from js and html
For images dynamically added through js, we can use the require() method to introduce
photo.src = require("./images/vue.jpeg");
Package preview, the results are as follows
The image is packaged and output, but the src path is incorrect and becomes a Module object. That's because the image processed by file loader is exported using ESModule by default, but we use commonJS to import it. There are two ways to solve this problem
Method 1: modify the file loader parameter (recommended, because the processing in html is also introduced using commonJS)
Method 2: modify the code in js as follows
photo.src = require("./images/vue.jpeg").default; // perhaps import img from "./images/vue.jpeg" photo.src = img;
For images in html, we can use html loader or html withimg loader to process them. Take html loader as an example
Install HTML loader, add configuration, and repackage
npm i html-loader -D
{ test: /\.html$/, use: "html-loader" }
So far, the pictures in css, js and html can be packaged and processed correctly, but note that the title in the head is not parsed by htmlWebpackPlugin
Because after processing with html loader, htmlWebpackPlugin cannot parse the ejs syntax in html, but outputs it as a string. Therefore, when there is ejs syntax in html, we can't use html loader to process images, but directly use ejs syntax to introduce
<img src="<%= require('./src/images/webpack.jpg') %>">
So far, all our files are exported to dist directory, which is not convenient for later release and online. Therefore, we want different types of files to be exported to different directories, such as css files to style directory, pictures to images directory, js to js Directory
Modify the webpack configuration and repackage
// Modify output filename: "js/[name].js" // It was "[name].js" before modification // Add parameters to file loader options outputPath: "images" // Output to images in dist directory // MiniCssExtractPlugin add parameter new MiniCssExtractPlugin({ filename: "style/[name].css" })
You can see that the files are indeed packaged in the corresponding directory, but the pictures introduced by css are not displayed. Analyze the reasons
Images are placed in the images directory, and images / is automatically spelled in front of the image path introduced by css. However, because css is placed in the style directory, the relative path between css and images has changed, so the image path introduced by css cannot be displayed
This problem can be solved by adding a parameter to MiniCssExtractPlugin.loader
{ test: /\.css$/, use: [{ loader: MiniCssExtractPlugin.loader, options: { publicPath: "../" // Spell.. / in front of the resource path introduced by css. This is the added parameter } }, "css-loader"] }
Pack again to see the effect
ok! The problem of picture display has been solved perfectly. Next, we will make some minor optimization
- Use URL loader instead of file loader. URL loader will encode and package small images into files based on 64 to reduce the number of network requests
- Use image webpack loader to compress images
npm i url-loader image-webpack-loader -D
{ test: /\.(jpe?g|png|gif|svg)$/, use: [{ loader: "url-loader", options: { name: "[name]-[contenthash:10].[ext]", outputPath: "images", limit: 10 * 1024, // Indicates that pictures less than 10k will be encoded by base64 fallback: "file-loader", // Pictures larger than 10k are processed by file loader. The default value is not set esModule: false } }, { loader: "image-webpack-loader", options: { disabled: true // When developing or using webpack dev server, it can speed up the initial compilation and, to a lesser extent, the subsequent compilation (from official documents) } }] }
It can be seen that only bg.jpeg (21k compressed to 19k) is packaged for output, while webpack.jpg (9.9k) and vue.jpeg (7k) are encoded by base64 and directly packaged into the file. That's all for the processing of pictures