In this era of inner scroll king, inner scroll culture has penetrated into all aspects of work and life. If you do not soar in the ocean of knowledge, you will drown in it. As a new generation of migrant workers, in IQ and diligence have been double crush by the workers at the same time, in the face of changing brick (programming) skills, the speed of learning has not caught up with the speed of forgetting, but also have to endure tears to embrace change, constantly beat strange upgrade.
Recently, I sorted out my previous webpack development experience and summarized an introductory note. Welcome everyone to watch and criticism.
As Web applications have become more complex and larger, front-end technologies have developed rapidly, and many of the best front-end frameworks, new languages, and other related technologies (as shown in the figure below) have emerged, which has greatly improved our development efficiency
However, we all know that one thing these technologies have in common is that the source code doesn’t run directly in the browser. At this point, we need to use build tools to convert this code into browser-executable JS, CSS, and HTML. This puts more demands on the front-end build tools.
There have been a number of build tools throughout history, some common ones are as follows:
Among them, Webpack stands out as the most popular build tool by virtue of its powerful functions and good use experience, as well as its huge community support.
Before we get down to business, let’s take a quick look at WebPack.
Webpack profile
Webpack is a static module packaging tool for modern JavaScript applications, according to its website. When WebPack processes an application, it internally builds a Dependency graph from one or more entry points, and then assembles each module you need in your project into one or more bundles, which are static resources for displaying your content.
Some core concepts of Webpack:
- Entry: An Entry that indicates which module Webpack should use as a starting point for building its internal dependency Graph.
- Output: Outputs a result that tells Webpack where to Output the bundles it creates and how to name those files.
- Module: Module, in Webpack everything is a Module, a Module corresponds to a file. Webpack recursively finds all dependent modules starting from the configured Entry.
- Chunk: a Chunk is a code block. A Chunk is composed of multiple modules for code merging and splitting.
- Loader: Module code converter that allows WebPack to process files of any type other than JS and JSON and convert them into valid modules for use by applications and to be added to dependency diagrams.
- Plugin: Extension plug-in. A number of events are broadcast during the life cycle of a WebPack run, and the Plugin can listen for these events and change the output when appropriate through the API provided by WebPack. Common examples are: package optimization, resource management, and injection of environment variables.
- Mode: Mode that tells Webpack to use the built-in optimizations for that Mode
- Webpack supports all ES5-compliant browsers (IE8 and above).
The role of Webpack
Webpack has many functions, just to list a few:
Loader and Plugin mechanisms can be used to further expand the capabilities and implement personalized functions according to the needs of the project.
** foreshadows so much, now back to the theme! **
Webpack is a front-end resource loading/packaging tool written by NodeJS, provided by NodeJS powerful file processing, IO capabilities.
Loader and Plugin are pillar capabilities in Webpack. Loaders and plugins play a decisive role in the build process. Here are some common Loaders and plugins in Webpack.
Loader
Introduction to the
Webpack provides a mechanism for handling multiple file formats. This is the Loader, which we can think of as a converter that converts files of a certain format into packaged modules supported by Wwebpack.
In Webpack, everything is a module. Common Javascript, CSS, Less, Typescript, Jsx, images and other files are modules. Loading of different modules is managed uniformly through module loaders. We can configure the rules in the module.rules field.
Loader features
-
Loader is essentially a function, output=loader(input) // input can be a string of project source files, but also the result of the conversion of the previous loader;
-
The first loader passes only one argument: the contents of the resource file;
-
Loader supports chain calls. Webpack delivers resources to Loader in order of array from back to front.
-
Supports synchronous or asynchronous functions.
The code structure
The code structure is usually as follows:
// source: resource input, for the first loader to execute the content of the resource file; The subsequent loaders are the execution results of the previous loader
// sourceMap: The sourceMap structure of the code is optional
// data: Optional argument, other information that needs to be passed in the Loader chain, such as posthTML/posthTML -loader will pass the AST object of the argument through this argument
const loaderUtils = require('loader-utils');
module.exports = function(source, sourceMap? , data?) {
// Get the options passed by the user to the current Loader
const options = loaderUtils.getOptions(this);
// TODO: this is the logic to convert source
return source;
};
Copy the code
The commonly used Loader
1. babel-loader
Babel-loader is based on Babel and is used to parse JavaScript files. Babel has a wealth of presets and plugins. Babel configuration can be written directly to options or to a separate configuration file.
Babel is a Javscript compiler that compiles advanced syntax (mainly ECMAScript 2015+) into lower version syntax supported by the browser. It can help you write code with the latest version of Javascript and improve development efficiency.
Webpack uses Babel via babel-loader.
Usage:
#Environmental requirements:
webpack 4.x || 5.x | babel-loader 8.x | babel 7.x
#Install dependency packages:
npm install -D babel-loader @babel/core @babel/preset-env webpack
Copy the code
Then, we need to create a Babel configuration file to specify the compiled rules.
The two core components of the Babel configuration are plugins and presets.
The Babel preset can be thought of as a set of Babel plug-ins, consisting of a series of plug-ins.
Common preset:
- @ Babel/preset – env ES2015 + syntax
- @babel/preset-typescript TypeScript
- @babel/preset-react React
- @babel/preset-flow Flow
Plug-ins and default execution order:
- The plug-in executes before default
- The plug-in execution order is the plug-in array executed from front to back
- The default execution order is that the default array is executed from back to front
Webpack configuration code:
// webpack.config.js
module: {
rules: [{test: /\.m? js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader'.options: {
presets: [['@babel/preset-env', { targets: "defaults"}]],plugins: ['@babel/plugin-proposal-class-properties'].// Cache the loader to the specified directory, the default is node_modules/. Cache /babel-loader, after the webpack build, will try to read the cache
cacheDirectory: true,}}}]}Copy the code
Options can also be written to a configuration file. Many other tools have similar configuration files: ESLint (.eslintrc), Prettier (.prettierrc).
Presets and plugins are the only presets we need to configure. The following code is used as an example:
// babel.config.js
module.exports = (api) = > {
return {
presets: [
'@babel/preset-react'['@babel/preset-env', {
useBuiltIns: 'usage'.corejs: '2'.targets: {
chrome: '58'.ie: '10'}}]],plugins: [
'@babel/plugin-transform-react-jsx'.'@babel/plugin-proposal-class-properties']}; };Copy the code
Recommended reading:
- Babel configuration file related documents
- The plugin manual
2. ts-loader
TypeScript loader for WebPack that packs and compiles TypeScript
Install dependencies:
npm install ts-loader --save-dev
npm install typescript --dev
Copy the code
The Webpack configuration is as follows:
// webpack.config.json
module.exports = {
mode: "development".devtool: "inline-source-map".entry: "./app.ts".output: {
filename: "bundle.js"
},
resolve: {
// Add `.ts` and `.tsx` as a resolvable extension.
extensions: [".ts".".tsx".".js"]},module: {
rules: [
// all files with a `.ts` or `.tsx` extension will be handled by `ts-loader`
{ test: /\.tsx? $/, loader: "ts-loader"}}};Copy the code
You also need the typescript compiler’s configuration file tsconfig.json:
{
"compilerOptions": {
// The target language version
"target": "esnext".// A template standard for generating code
"module": "esnext"."moduleResolution": "node".// Allows the compiler to compile JS, JSX files
"allowJS": true.// Allows errors to be reported in JS files, usually with allowJS
"checkJs": true."noEmit": true.// Whether to generate the source map file
"sourceMap": true.// Specify the JSX mode
"jsx": "react"
},
// Compile the file or directory to be compiled
"include": [
"src"."test"].// A file or folder that the compiler needs to exclude
"exclude": [
"node_modules"."**/*.spec.ts"]}Copy the code
See the official website for more configurations
3. markdown-loader
Markdown compiler and parser
Usage:
Simply add the Loader to your configuration and set options.
Import markdown files in js code:
// file.js
import md from 'markdown-file.md';
console.log(md);
Copy the code
Webpack configuration:
// wenpack.config.js
const marked = require('marked');
const renderer = new marked.Renderer();
module.exports = {
// ...
module: {
rules: [{test: /\.md$/,
use: [
{
loader: 'html-loader'
},
{
loader: 'markdown-loader'.options: {
pedantic: true,
renderer
}
}
]
}
],
},
};
Copy the code
4. raw-loader
Files can be imported as strings
// app.js
import txt from './file.txt';
// webpack.config.js
module.exports = {
module: {
rules: [{test: /\.txt$/,
use: 'raw-loader'}}}]Copy the code
5. file-loader
Used for processing file type resources, such as JPG, PNG and other images. The returned value is publicPath
// file.js
import img from './webpack.png';
console.log(img); / / the compiled: https://www.tencent.com/webpack_605dc7bf.png
// webpack.config.js
module.exports = {
module: {
rules: [{test: /\.(png|jpe? g|gif)$/i,
loader: 'file-loader'.options: {
name: '[name]_[hash:8].[ext]'.publicPath: "https://www.tencent.com",},},],},};Copy the code
The image path in the CSS file becomes the following:
/* index.less */
.tag {
background-color: red;
background-image: url(./webpack.png);
}
/* After compiling: */
background-image: url(https://www.tencent.com/webpack_605dc7bf.png);
Copy the code
6. url-loader:
Url-loader can set a different operation based on the size of the image. If the image size is larger than the specified size, the image will be packed resources, otherwise, the image will be converted to base64 string into js file.
module.exports = {
module: {
rules: [{test: /\.(png|jpg|jpeg)$/,
use: [
{
loader: 'url-loader'.options: {
name: '[name]_[hash:8].[ext]'.// the unit is (b) 10240 => 10kb
// If the size is smaller than 10KB, it will be converted to base64 and packed into js file. If the size is larger than 10KB, it will be packed into the corresponding directory
limit: 10240,}}]}]}}Copy the code
7. svg-sprite-loader
The referenced SVG files are stuffed into each symbol and combined into a large SVG Sprite, which is rendered using the <use> SVG icon ID passed in. Finally, place the large SVG inside the body. The SYMBOL ID is your filename unless specified.
This loader can be used with SvGo-Loader, which is an OPTIMizer for SVG. It can delete and modify SVG elements, collapse content, move attributes, etc., without expanding the description. Those who are interested can go to the official introduction.
** Uses: can be used to develop a unified icon management library. **
** Example code: **
// js file
import webpack from './webpack/webpack.svg';
const type = 'webpack';
const svg = `<svg>
<use xlink:href="#${type}"/>
</svg>`;
const dom = `<div class="tag">
${svg}
</div>`;
document.getElementById('react-app').innerHTML = dom;
// webpack.config.js
module.exports = {
module: {
rules: [{test: /\.(png|jpg|jpeg)$/,
use: [
{
test: /\.svg$/,
use: [
{
loader: 'svg-sprite-loader'
},
'svgo-loader']},]}]}Copy the code
Principle: Using the SYMBOL element of SVG, wrap each icon in a symbol and use that symbol.
8. style-loader
Insert the CSS into the DOM by injecting a <style> tag
Note:
-
If for some reason you need to extract CSS as a file (i.e. don’t store CSS in a JS module), then you need to use the mini-CSS-extract-plugin (described in the Pugin section below);
-
For development modes (including webpack-dev-server) you can use style-loader because it introduces CSS via the <style></style> tag and loads faster;
-
Do not use style-loader and mini-CSS-extract-Plugin for the same CSS module!
See postCSS-loader below for code examples
9. css-loader
Handle only the various load syntax of CSS (@import, URL () functions, etc.), just as JS parses import/require()
See postCSS-loader below for code examples
10. postcss-loader
PostCSS is a tool that allows you to transform styles using JS plug-ins. Lint these plugins examine your CSS, support CSS Variables and Mixins, compile advanced CSS syntax not yet widely supported by browsers, inline images, and many other nice features.
PostCSS is widely used in the industry. PostCSS’s Autoprefixer plug-in is one of the most popular CSS processing tools.
Autoprefixer adds a browser prefix that uses the data above Can I Use.
The installation
npm install postcss-loader autoprefixer --save-dev
Copy the code
Code examples:
// webpack.config.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const isDev = process.NODE_ENV === 'development';
module.exports = {
module: {
rules: [{test: /\.(css|less)$/,
exclude: /node_modules/,
use: [
isDev ? 'style-loader' : MiniCssExtractPlugin.loader,
{
loader: 'css-loader'.options: {
importLoaders: 1,}}, {loader: 'postcss-loader'
},
{
loader: 'less-loader'.options: {
lessOptions: {
javascriptEnabled: true}}}]}}Copy the code
Then create postcss.config.js in the root directory of the project and set the supported browsers
module.exports = {
plugins: [
require('precss'),
require('autoprefixer') ({'browsers': [
'defaults'.'not ie < 11'.'last 2 versions'.'> 1%'.'iOS 7'.'last 3 iOS versions']]}})Copy the code
As of now, PostCSS has more than 200 plug-ins. You can find them in the plugins list or in the search directory
To learn more, go to the link
11. less-loader
Parse less and convert to CSS
See postCSS-loader above for a code example
To learn more, go to the link
Plugin
Introduction of the Plugin
Webpack is like a production line that goes through a series of processes to convert source files into output. Each process on this production line has a single responsibility. There are dependencies between multiple processes. Only after the current process is completed can the next process be handled. A plug-in is like a function that plugs into a production line and works with resources on the production line at a specific time.
Webpack organizes this complex production line through Tapable. Webpack broadcasts events as it runs, and the plug-in only needs to listen for the events it cares about to join the production line and change how the production line works. Webpack’s event flow mechanism ensures the orderliness of plug-ins and makes the whole system very extensible.
– “Simple Webpack”
The Plugin is commonly used
1. copy-webpack-plugin
Copy an existing single file or entire directory to the build directory.
const CopyPlugin = require("copy-webpack-plugin");
module.exports = {
plugins: [
new CopyPlugin({
patterns: [{from: './template/page.html'.to: `${__dirname}/output/cp/page.html`},],}),],};Copy the code
2. html-webpack-plugin
The basic function is to generate HTML files
-
A single-page application can generate one HTML entry, and a multi-page application can configure multiple instances of htML-webpack-Plugin to generate multiple page entries
-
Introduce external resources for HTML, such as script and link, insert the relevant chunk of entry configuration and the CSS file extracted by mini-CSS-extract-plugin into the HTML file generated based on the template file set by the plug-in. This is done by inserting link into the head and script into the head or body.
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
news: [path.resolve(__dirname, '.. /src/news/index.js')].video: path.resolve(__dirname, '.. /src/video/index.js'),},plugins: [
new HtmlWebpackPlugin({
title: 'news page'./ / generated file name In terms of relative to webpackConfig. The output. The path path
filename: 'pages/news.html'.// Generate a file template for filename
template: path.resolve(__dirname, '.. /template/news/index.html'),
chunks: ['news']}),new HtmlWebpackPlugin({
title: 'video page'.// The generated file name
filename: 'pages/video.html'.// Generate a file template for filename
template: path.resolve(__dirname, '.. /template/video/index.html'),
chunks: ['video']]}}),Copy the code
3. clean-webpack-plugin
By default, this plug-in removes all files in webpack’s output.path and any unused resources after each successful rebuild.
This plugin is used very frequently in production environments, where many bundles are hash generated and new ones are generated each time if not cleaned up, resulting in huge folders.
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
plugins: [
new CleanWebpackPlugin(),
]
};
Copy the code
4. mini-css-extract-plugin
This plug-in extracts CSS into a separate file, creating a CSS file for each JS file that contains CSS.
// It is recommended that mini-CSS-extract-plugin be used together with CSS-loader
// Add loader and plugin to the webpack configuration file
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
plugins: [new MiniCssExtractPlugin()],
module: {
rules: [{test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader'],}],},};Copy the code
You can see this plug-in in conjunction with the style-loader introduction above.
5. webpack.HotModuleReplacementPlugin
Module hot replacement plug-in, otherwise known as HMR.
This feature replaces, adds, or removes modules while the application is running without having to reload the entire page. Significantly speed up development in the following ways:
-
Preserve application state that is lost during a full page reload.
-
Update only the changes to save valuable development time.
-
When CSS/JS changes are made in the source code, they are immediately updated in the browser, which is almost equivalent to changing styles directly in the browser DevTools.
There are two boot modes:
-
Introducing plug-in webpack. HotModuleReplacementPlugin and setting devServer. Hot: true
-
Command line add –hot argument
Package. Json configuration:
{
"scripts": {
"start": "NODE_ENV=development webpack serve --progress --mode=development --config=scripts/dev.config.js --hot"}}Copy the code
The configuration of Webpack is as follows:
/ / scripts/dev. Config. Js file
const webpack = require('webpack');
const path = require('path');
const outputPath = path.resolve(__dirname, './output/public');
module.exports = {
mode: 'development'.entry: {
preview: [
'./node_modules/webpack-dev-server/client/index.js? path=http://localhost:9000',
path.resolve(__dirname, '.. /src/preview/index.js')]},output: {
filename: 'static/js/[name]/index.js'.// The name of the dynamically generated chunk file when it is exported
chunkFilename: 'static/js/[name]/chunk_[chunkhash].js'.path: outputPath
},
plugins: [
// In most cases no configuration is required
new webpack.HotModuleReplacementPlugin(),
],
devServer: {
// Configure only when static files need to be supplied
contentBase: outputPath,
// publicPath: '', // default value is '/'
compress: true.port: 9000.watchContentBase: true.hot: true.// Open the browser after the server starts
open: true.// Specify the page to view when opening the browser
openPage: ['pages/preview.html'].// Write the generated file to the hard disk. Path to the directory configured
writeToDisk: true,}}Copy the code
Note: HMR should never be used in a production environment.
6. webpack.DefinePlugin
Creates a global constant that can be configured at compile time. This can be very useful when the development mode and production mode are built to allow different behaviors.
Because this plug-in performs text substitution directly, the given value must contain the actual quotes inside the string itself.
In general, there are two ways to achieve this effect, using ‘ ‘production’ ‘, or using json.stringify (‘production’)
// webpack.config.js
const isProd = process.env.NODE_ENV === 'production';
module.exports = {
plugins: [
new webpack.DefinePlugin({
PAGE_URL: JSON.stringify(isProd
? 'https://www.tencent.com/page'
: 'http://testsite.tencent.com/page')})]}// use it directly in the code
console.log(PAGE_URL);
Copy the code
7. webpack-bundle-analyzer
You can see the size of each module of the project, which can be optimized as needed. A Bundle file analysis tool for WebPack that presents bundles as interactively scaled Treemaps.
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [
new BundleAnalyzerPlugin()
]
}
Copy the code
Start the service:
-
Production environment: NODE_ENV=production NPM run build
-
NODE_ENV=development NPM run start
End result:
To learn more, go to the link
8. SplitChunksPlugin
Code segmentation.
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
optimization: {
splitChunks: {
/ / delimiter
// automaticNameDelimiter: '~',
// all, async, and initial
chunks: 'all'.// It inherits/overwrites all the parameters in splitChunks, and provides three additional configurations: test, Priority, and reuseExistingChunk
cacheGroups: {
vendors: {
The default is all modules, which can match the module path or chunk name. If a chunk name is matched, all modules in it will be selected
test: /[\\/]node_modules\/antd\//.// priority: indicates the extraction weight. A higher number indicates a higher priority. Because a module may satisfy multiple cacheGroups conditions, the highest weight determines which one to extract;
// priority: 3,
// reuseExistingChunk: Indicates whether to use an existing chunk. If true, it indicates that no new chunk will be created if the current chunk contains modules that have been extracted.
reuseExistingChunk: true.name: 'antd'}}}},}Copy the code