🛴 preface
stay The previous two articles In, we explained the introduction of webpack. However, after the introduction knowledge is understood, it must be applied to specific cases.
Therefore, in the following article, we will lead you to learn about some actual case configurations of webpack, including the packaging configuration of third-party libraries, PWA and ts, as well as the advanced operation of webpack devserver. We also need to focus on how to optimize the performance of webpack.
Let's start this article~ 🚦
🚌 1, Packaging of Library
Suppose we want to develop a component library or a function library, how should we package such library code with webpack?
1. webpack packaging Library
If we write a lot of logic code now, at the same time, we package these logic codes, and after packaging, all of them are generated in mondaylib. Under dist folder JS file.
Well, now the library is generated. How can our users introduce mondaylib?
In general, others can introduce our library in the following ways:
//Mode 1 import mondaylib from 'mondaylib' //Mode II const mondaylib = require('mondaylib') //Mode III require(['mondaylib'], function(){ })
Therefore, if we want our users to introduce this library, we need to use webpack config. JS. The specific configuration is as follows:
const path = require('path'); module.exports = { mode: 'production', entry: './src/index.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'mondaylib.js', //The libraryTarget is configured here. umd means that the syntax of commonJS is supported libraryTarget: 'umd' } }
libraryTarget: 'umd' means that the syntax of commonJS is supported, so the above three methods can be introduced. At the same time, the libraryTarget can also be set to other values, such as this and window.
libraryTarget: 'this' means that I want to mount the mondaylib variable on the page. libraryTarget: 'window' is expressed as the variable mondaylib, which will be mounted on the window.
In addition to the above three cases, there are other special cases, as follows:
<script src="mondaylib.js"></script>
At this point, we need to be in webpack config. JS:
const path = require('path'); module.exports = { mode: 'production', entry: './src/index.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'mondaylib.js', //Mount the packaged generated code on the global variables of the page library: 'mondaylib', //The libraryTarget is configured here. umd means that the syntax of commonJS is supported libraryTarget: 'umd' } }
The first library is the attribute value, and the second mondaylib is our library name. This configuration means that the generated code will be packaged, that is, mondaylib JS library, which is attached to global variables.
2. Library reference conflict
Suppose we now introduce lodash into the above mondaylib library. Then, when the user uses it, the user introduces the lodash library again. Like the following code:
import _ from 'lodash'; //The mondaylib library has previously introduced the lodash library import mondaylib from 'mondaylib';
So now, how can we avoid this problem? Let's webpack config. JS. The specific code is as follows:
const path = require('path'); module.exports = { externals: ["lodash"] }
From the above code, we can know that through the configuration of externals: [lodash], we can tell webpack that if lodash is encountered in the mondaylib library during the packaging process, we should avoid it and do not package. In this way, you can effectively avoid the problem of multiple references to the library and reduce the packaging size of the code.
externals has another special configuration, as shown in the following code:
module.exports = { externals: { // It indicates that if lodash is used in the environment of commonjs, it must be called lodash when lodash is loaded lodash: { commonjs: 'lodash' } } }
If configured in this way, it is intended to indicate that if the lodash library is used in the environment of commonjs, it must be named lodash when loading, rather than arbitrarily. Like this:
//✔ Can be used: named lodash import lodash from 'lodash' //✘ not available: not named lodash import _ from 'lodash'
🚍 2, Packaging configuration of PWA
1. What is PWA
PWA is called Progressive Web Application.
PWA is a relatively new front-end technology. What kind of technology is it?
The effect PWA can achieve is that if you visit a website, it may be successful for the first time, but suddenly the server of the website hangs up. Then you can't visit the website at this time. However, PWA will cache the first page you visit. After that, even if the server hangs up, you can still show the page you saw before.
Therefore, there is a plug-in in webpack to achieve this effect. Let's find out~
2. PWA in webpack
Step 1: install the plug-in. The specific codes are as follows:
npm install workbox-webpack-plugin --save-dev
Step 2: in webpack The plug-in is introduced into prod.js and used. The specific codes are as follows:
const WorkboxPlugin = require('workbox-webpack-plugin'); module.exports = { plugins: [ new WorkboxPlugin.GenerateSW({ clientsClaim: true, skipWaiting: true }) ], }
Usually, we only need to introduce PWA into prod, which is an online environment, and this problem does not need to be considered in the development environment. Through the above configuration, after the project is packaged, two new files will be generated in the dist directory, one is service worker JS, and the other is precache JS file, these two files are for us to use PWA.
Step 3: import the above files. The specific codes are as follows:
if('serviceWorker' in navigator){ window.addEventListener('load', () => { navigator.serviceWorker.register('/service-worker.js') .then(registration => { console.log('service-worker registed'); }).catch(error => { console.log('service-worker regist error'); }) }) }
We need to write a business code in the entry file and introduce service worker JS file to help us do PWA. At this time, we package the project. After that, if the server suddenly hangs up, don't worry. PWA will help us load the original page for us to browse.
🚎 3, Packaging configuration of TypeScript
1. Cited examples
We all know that for different developers, different people write different code styles and forms, so it is difficult to ensure the maintainability of the project in the later stage. Well, at this time, Typescript, which was popular in 2018, appeared. TS standardizes a set of js standards. Therefore, we can standardize our code through ts in the writing of project code, and make the maintainability and scalability of our project better.
Next, let's learn how to support ts syntax through the configuration change of webpack.
2. Configuration of ts by webpack
(1) Background
Suppose we have a section of ts code that needs to be compiled. The specific code is as follows:
class Greeter{ greeting: string; constructor(message: string){ this.greeting = message; } greet(){ return "Hello, " + this.greeting; } } let greeter = new Greeter("world"); let button = document.createElement('button'); button.textContent = "Say Hello"; button.click = function(){ alert(greeter.greet()); } document.body.appendChild(button);
Now, we want webpack to compile this ts code. What should we do?
(2) Configuration steps
Step 1: install TS loader. The specific commands are as follows:
npm install ts-loader typescript -D
Step 2: we are on webpack config. JS file. The specific codes are as follows:
const path = require('path'); module.exports = { mode: 'production', entry: './src/index.tsx', module: { rules: [{ test: /\.tsx?$/, use: 'ts-loader', exclude: /node_modules/ }] }, output: { filename: 'bundle.js', path: path.resolve(__dirname, 'dist') } }
Step 3: configure tsconfig JSON file. The specific codes are as follows:
{ "compilerOptions": { "outDir": "./dist", "module": "es6", "target": "es5", "allowJs": true } }
3. ts identify the third party Library
Sometimes, we will call the join method in lodash, but if we do not carry out special processing, we will not report an error if we normally introduce and use the lodash Library in the tsx file. Therefore, we need to install another ts library to handle it. The specific steps are as follows:
Step 1: install the @ types/lodash library. The specific commands are as follows:
npm install @types/lodash --save-dev
After installing this library, ts can identify some functions and methods of lodash. Once there is a wrong reference, it will give an error prompt.
If you have a small partner, you will have a question: does ts have the type files of all such libraries (such as jQuery and other libraries)?
The answer is, of course, No. We can go to a website on github 👉https://microsoft.github.io/TypeSearch/ If the search results are found, we can install it with @ type / library name, and then the tsx file will support the type check of the library.
🚕 4, Advanced operation of WebpackDevServer
1. WebpackDevServer implements request forwarding
In general, we can build a proxy server locally through charles fiddler tool. Through this proxy server, forward the interface address we want to request.
In webpack, we are provided with a tool, devserver Proxy . Next, we're at webpack config. JS. The specific code is as follows:
module.exports = { devServer: { proxy: { '/react/api': { target: 'http://www.mondaylab.com', //Realize the request forwarding of https web address secure: false, bypass: function(req, res, proxyOptions){ //If the requested content is an html address, it will directly return to the index.html address under the root path html content if(req.headers.accept.indexOf('html') !== -1){ console.log('Skipping proxy for browser request'); return './index.html'; // return false; // It means that if you encounter an html request, you can return whatever you should return } }, //Write header when the front end requests JSON, webpack will indirectly help us get the demo JSON data (request forwarding]) pathRewrite: { 'header.json': 'demo.json' }, //If some websites are anti crawler, we may not be able to cross domain. The following configuration is required to break through the limitation on origin changeOrigin: true, // Customize some content in the request header headers: { host: 'www.mondaylab.com', //Simulate some login operations when forwarding requests cookie: 'gfhgfh' } } } } }
2. WebpackDevServer solves the problem of single page application routing
For modern mainstream frameworks, like Vue js ,React.js and other frameworks are basically single page applications. So, in a single page application, for example, we want to start from http://mondaylab.com Jump to http://mondaylab.com/list , how to jump?
This is about the routing problem of a single page application. We need to be on webpack config. JS is configured as follows:
module.exports = { devServer: { //The first way historyApiFallback: true, /*Equivalent to historyApiFallback: { rewrites: [{ from: /\.*\/, to: '/list.html/' }] } */ /*The second way historyApiFallback: { rewrites: [{ from: /abc.html/, //Convert when accessing ABC HTML, list The content of HTML is displayed to: '/list.html/' }] } */ /*The third way: more flexible historyApiFallback: { rewrites: [{ //Indicates that when replacing a page, a function is used in the form of function, combined with some parameters of context //Do some js logic and put it in it to decide where it will jump in the end from: /^\/(libs)\/.*$/, to: function(context){ return '/bower_components' + context.match[0]; } }] } */ } }
It is worth noting that historyApiFallback can only be used in the development environment. If you are in the online environment, you need to ask the back-end partners to go to nginx or apache, follow some configurations of webpackDevServer, and make the same configuration on the back-end server. After configuration, the front-end can use the corresponding route.
🚖 5, Configuration of ESLint in Webpack
1. What is eslint
In our daily team development, everyone writes all kinds of code. For example, some people like to add a semicolon after the code, while others don't. Indirectly, this can easily lead to poor maintainability of our project. Therefore, we have introduced the content of ESLint to restrict the code specification and improve the maintainability and scalability of the project.
How is ESLint configured in Webpack?
2. How to install ESLint
Step 1: install the ESLint tool. The specific commands are as follows:
npm install eslint --save-dev
Step 2: constrain our code. We need to create a new configuration file to configure our ESLint specification. The specific commands are as follows:
npx eslint --init > Use a popular style guide Use a common code detection template > Airbnb > Do you use React Fill in according to your own needs y perhaps n > Javascript > Would you like to install them now with npm? Y
Step 3: use eslint to check the code specification. The specific codes are as follows:
npx eslint src
The above code means to use eslint to detect the code specification in the src directory.
3. Why should ESLint be configured in webpack
In the above, we learned that each development partner can use the command line to detect their own code specifications, but if we have to run such commands every time we write the code, we can see whether our code is reasonable or not. Will it be a little troublesome. At the same time, we can't guarantee that everyone's eslint code specification settings are the same.
Therefore, we can configure it in webpack to solve the above problems. The specific steps are as follows:
Step 1: install eslint loader. The specific command line is as follows:
npm install eslint-loader --save-dev
Step 2: configure webpack config. js . The specific codes are as follows:
module.exports = { devServer: { /*When we run webpack for packaging, Once there is a specification problem with the code, webpack An error reporting layer will pop up on the browser to prompt us*/ overlay: true }, module: { rules: [{ test: /\.js$/, exclude: /node_modules/, use: ['babel-loader', 'eslint-loader'] }] } }
After understanding the basic configuration, let's learn about some other configurations of eslint loader. The specific codes are as follows:
module.exports = { module: { rules: [{ test: /\.js$/, exclude: /node_modules/, use: ['babel-loader', { loader: 'eslint-loader', options: { //If there are some simple problems in the code, eslint loader will help us fix them automatically fix: true, //Reduce the loss of project performance caused by eslint in the packaging process cache: true }, //Force eslint loader to execute first fore: 'pre' }] }] } }
🏎️ 6, Webpack performance optimization
Careful partners may have found that the packaging speed of Webpack may be a little slow sometimes. Indirectly, it will waste a lot of time we shouldn't waste. So, let's talk about several ways to improve the packaging speed of Webpack.
1. Keep up with the iteration of Technology (node, NPM, Yan)
If we want to improve the packaging speed of webpack, we can upgrade the version of webpack, or upgrade the version of node, npm manager or yarn.
So why can upgrading these tools improve the packaging speed of webpack.
Let's think about it. When we update each version of webpack, we will certainly do a lot of internal version optimization. Therefore, when we update the version of webpack, we will certainly improve the speed. The same is true for node, npm and yarn updates.
Just imagine, if you don't upgrade, what's the significance of upgrading? Right.
2. Apply Loader on as few modules as possible
In general, the libraries of third-party modules have been packaged and compiled, so we need to update node when introducing loader for compilation_ Module files are ignored, or only a loader is used in a folder to increase our packaging speed. We can go to webpack config. JS. The specific code is as follows:
module.exports = { module: { rules: [{ test: /\.js$/, exclude: /node_modules/, //Or use the following method - > include //include: path.resolve(__dirname, '../src'), use: [{ loader: 'babel-loader' }] }] } }
Of course, according to the above idea, other loader s also have their corresponding precautions, which will not be described in detail here.
3. Rational use of plug-ins
Plug-ins should be used reasonably. Don't use those redundant and meaningless plug-ins. At the same time, we should also choose those plug-ins with better performance and officially recognized. In this way, we can effectively improve the packaging speed of webpack.
4. Reasonable configuration of resolve parameters
(1) Common configuration
Sometimes, we want to make some custom configurations for the imported files. What should we do? The specific configuration is as follows:
module.exports = { resolve: { extensions: ['js', 'jsx'], /** * 1.When you only import one directory, such as import child from '/ child/child' , * At this time, webpack doesn't know which file we want to import, * Then it will look for the index file first. If it cannot be found, it will continue to look for the child file */ mainFiles: ['index', 'child'], /** * alias, As the name suggests, it is an alias. * For example, you want to change the import method of a file to your own name * import Child from './Child' -> import Child from 'monday' */ alias: { monday: path.resolve(__dirname, '../src/Child'), } }, }
Next, the above parameters will be explained in detail.
(2) Parameter explanation
1)extensions
- For example, when import child from 'is introduced/ When "child / child", I'll look for it first/ child/child.js' file, can't find it, find it again '/ child/child.jsx 'file.
- css and picture files are generally not configured, because there may be a large number of css and pictures, and corresponding searches will be performed many times. Indirectly, I wanted to improve performance, but it turned out to be a waste of performance.
- Therefore, resource files such as css and jpg should be explicitly introduced; For logical files such as js and jsx, you can configure them in extesions for explicit introduction.
2)mainFiles
When you only import one directory, such as import child from '/ Child / child ', at this time, webpack doesn't know which file we want to import, so it will look for the index file first. If it can't find it, it will continue to look for the child file.
3)alias
- Alias, as the name suggests, is an alias. For example, you want to change the import method of a file to your own name → import child from '/ Child' -> import Child from 'monday' .
- It is often used in the case of multi-level directories.
5. Use DllPlugin to improve packing speed
Sometimes, we want to introduce third-party modules that are only analyzed when packaging for the first time, but not when packaging later. What should I do?
Step 1: create a new webpack dll. JS file and configure it. The specific codes are as follows:
const path = require('path'); const webpack = require('webpack'); module.exports = { mode: 'production', entry: { //Fill in the name of the third party library we want to package separately here vendors: ['react', 'react-dom', 'lodash'] }, output: { filename: '[name].dll.js', path: path.resolve(__dirname, '../dll'), /*Use the library to store all the code in the third-party module, Exposed through global variables*/ library: '[name]' }, plugins: [ /*After exposure, analyze the exposed module code with the help of DllPlugin plug-in, and finally generate manifest JSON file */ new webpack.DllPlugin({ //Perform DllPlugin analysis (file mapping) on the generated vendor library name: '[name]', // The path put by the analysis result, combined with the global variables after analysis, is in common JS path: path.resolve(__dirname, '../dll/[name].manifest.json') }) ] }
Step 2: install the add asset HTML webpack plugin. The specific commands are as follows:
npm install add-asset-html-webpack-plugin --save
Step 3: configure webpack common. JS file. The specific configuration is as follows:
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin'); const webpack = require('webpack'); module.exports = { entry: { main: './src/index.js', plugins: [ new HtmlWebpackPlugin({ template: 'src/index.html' }), /** * It refers to the index to be generated into the HTML webpack plugin plug-in Add some content to HTML */ new AddAssetHtmlWebpackPlugin({ filepath: path.resolve(__dirname, '../dll/vendors.dll.js') }), /** * 1.Using the DllReferencePlugin plug-in, * This plug-in will go to '/ dll/vendors.manifest.json 'to find the mapping relationship of the third-party module, * If the mapping relationship can be found, then webpack will know that there is no need to package this third-party module, * Directly from vendors dll. JS can be used * 2.If it is found and no longer in the mapping relationship, it will go to the node again_ Modules * */ new webpack.DllReferencePlugin({ manifest: path.resolve(__dirname, '../dll/vendors.manifest.json') }) ] } }
Step 4: configure package JSON file. The specific codes are as follows:
{ "scripts": { "build:dll": "webpack --config ./build/webpack.dll.js" } }
Package the third-party library by running npm run build:dll command.
6. Control package file size
When we do project packaging, we should make the generated files as small as possible. Sometimes when we are writing code, we often introduce some useless modules into the page, that is, some modules we use.
At this time, if you do not configure tree shaking, it will easily lead to a large amount of redundant code during packaging. These redundant codes, indirectly, will drag down the packaging speed of our webpack.
Therefore, we should control the file size when packaging. Refer to the following steps:
- Configure tree shaking;
- Split a large file into multiple small files through SplittingChunk.
7. Multi process packaging
Webpack runs through node, so its packaging process is single threaded. Sometimes, we can also use the multi process in node to help us improve the packaging speed of webpack.
Common tools include thread loader, parallel webpack, happypack and other tools. You can find relevant information according to your own needs, select the most suitable tool for your project and package it. This section will not be explained in detail~
8. Rational use of sourceMap
Generally, the more detailed the sourceMap is, the slower the packaging will be. Therefore, when packaging, we should select the most appropriate sourceMap configuration according to the current development environment or production environment to generate our corresponding code debugging file.
In this way, on the one hand, we can ensure that even if we find errors in the code. On the other hand, you can also improve the packaging speed as much as possible.
9. Analyze the packing results with stats
When packaging the project, we can generate stats files of this packaging situation through commands. Then, we can analyze the packaging situation in this packaging process with the help of some online or local packaging analysis tools.
For example, analyze which module takes a long time to package and which module takes a short time to package and analyze, and optimize it according to the specific situation.
10. Development environment memory compilation
Using webpackDevServer to compile, it will not put the packaged files in the dist directory, but put them in the memory of our computer.
11. Elimination of useless plug-ins in development environment
For example, we do not need to compress the code in the development environment. Therefore, we should not configure the corresponding compression plug-ins in the development environment, but only in the production environment. In this way, you can reduce some unnecessary packaging time.
🏍️ 7, Multi page packaging configuration
Generally speaking, whenever we do packaging, we basically package single page applications. What is a single page, that is, there is only one index HTML file. At present, the mainstream frameworks, such as vue and react, are single page applications. However, some older frameworks, such as jquery and zepto, may require multi page application packaging.
Therefore, following this topic, let's talk about how to package and configure multi page applications in webpack.
We're on webpack common. JS. The specific code is as follows:
const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: { //Import multiple entry files main: './src/index.js', list: './src/list.js' }, plugins: [ new HtmlWebpackPlugin({ template: 'src/index.html', filename: 'index.html', //chunk indicates which of these html files to import chunks: ['runtime', 'vendors', 'main'] }), new HtmlWebpackPlugin({ template: 'src/index.html', filename: 'list.html', chunks: ['runtime', 'vendors', 'list'] }) ] }
Through the above code, we can know that the configuration of entry and plugins is added to add multiple entry pages, so as to achieve the effect of multi page application configuration.
🛵 8, Conclusion
Through the above explanation, I believe you have a certain understanding of the actual configuration of webpack in some scenarios. The above content is also relatively simple. You can broaden your knowledge according to the corresponding knowledge points, so as to better apply it to practical projects.
Here, the actual case configuration of webpack is over! I hope it will help you~
If the article is wrong or doesn't understand, please leave a message in the comment area 💬
🐣 One More Thing
(: recommended in previous periods)
- Getting started with webpack Basics 👉 No, the front end of the webpack may be picked up. Ten thousand words summarize the super entry core knowledge of webpack
- Introduction and advanced knowledge of webpack 👉 Can't you enjoy the core knowledge of webpack? Come and watch advanced knowledge
(: Fan Wai Pian)
- Pay attention to the official account of Monday's research room. First, we will focus on quality articles.
- If this article is useful to you, remember to leave a footprint jio before you go~
- The above is the whole content of this article! See you next time! 👋👋👋