Webpack has become the most popular and active packaging tool with its powerful features. It is also a “soft skill” that senior programmers must master when interviewing. The author introduces the use of Webpack based on the experience in the project. This article is the introduction of webpack entry, output and the use of various loaders, plugins and development environment, technical leaders please CTRL + W.
All the demo code for this article is in Webpackage Demo
concept
Take a look at the definition of Webpack:
In essence, Webpack is a static Module bundler for modern JavaScript applications. When WebPack works with an application, it recursively builds a Dependency graph containing every module the application needs, and then packages all of those modules into one or more bundles.
First, WebPack is a packer of static modules, so called static modules, including scripts, style sheets, images, and so on. When webPack is packaged, it first iterates through all static resources, builds a dependency graph based on resource references, and then divides modules into one or more bundles. Again, the diagram on piao’s official website vividly describes the process:
When it comes to WebPack, we have to mention four core concepts of WebPack
- Entry: Indicates which module WebPack should use as a starting point for building its internal dependency graph
- Output: Where do I export the bundles it creates
- Loader: Enables Webpack to handle non-javascript files
- Plugins: Used to perform a wider range of tasks
Your first packer
Let’s first install WebPack globally:
NPM install webpack webpack-cli -gCopy the code
Webpack can be built directly from the command line without using configuration files as follows:
webpack <entry> [<entry>] -o <output>
Copy the code
Here entry and output correspond to the above concept of entry and input, let’s create a new entry file:
//demo1/index.js
var a = 1
console.log(a)
document.write('hello webpack')
Copy the code
With the import file we also need to define the input path dist/bundle.js from the command line:
webpack index.js -o dist/bundle.js
Copy the code
Webpack then generates the packaged files in the dist directory.
We can also create a new HTML file in the project directory and import the bundled bundle.js file to see the effect.
The configuration file
Command line packaging is limited to simple projects. If our project is complex and has multiple entries, we can’t write down the entries every time we pack. Therefore, in general projects, configuration files are used for packaging; The commands for the configuration file are as follows:
webpack [--config webpack.config.js]
Copy the code
The default configuration file name is webpack.config.js. There are often multiple configuration files in a project. We can configure different files for different environments by using –config:
// Production environment configuration
webpack --config webpack.prod.config.js
// Development environment configuration
webpack --config webpack.dev.config.js
Copy the code
Multiple configuration types
The config file exports a configuration object through module.exports:
//webpack.config.js
var path = require('path');
module.exports = {
mode: 'development'.// Import file
entry: './index.js'.// Output directory
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'}};Copy the code
In addition to exporting an object, you can also export it as a function. The function carries parameters such as environment variables passed in from the command line. In this way, environment variables can be easily configured. For example, we can distinguish the formal and online development environments on the packaging line using env:
var path = require('path');
//env: environment object
module.exports = function(env, argv){
return {
// Other configurations
entry: './index.js'.output: {}}};Copy the code
Alternatively, you can export as a Promise for asynchronously loading configurations, such as dynamically loading entry files:
module.exports = (a)= > {
return new Promise((resolve, reject) = >{
setTimeout((a)= >{
resolve({
entry: './index.js'.output: {}})},5000)})}Copy the code
The entrance
As mentioned above, the entry is the starting point for the entire dependency; Our common single-entry configuration is a page entry:
module.exports = {
entry: './index.js',}Copy the code
It is short for:
module.exports = {
entry: {
main: './index.js'}},Copy the code
However, we may have more than one module in a page, so we need to inject multiple dependent files together. In this case, we need to use arrays.
module.exports = {
entry: [
// Multicast map module
'./src/banner.js'./ / the main module
'./src/index.js'.// Bottom module
'./src/foot.js'],}Copy the code
Sometimes a project may have more than one page, and multiple pages need to be packaged separately. Entry supports the form of incoming objects, and the code is in Demo3:
//demo3
module.exports = {
entry: {
home: './src/home.js'.list: './src/list.js'.detail: ['./src/detail.js'.'./src/common.js',}}Copy the code
Webpack then builds three different dependencies.
The output
The Output option controls how WebPack enters the compiled file module; There can be multiple entries, but only one output can be configured:
module.exports = {
entry: './src/index.js'.output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'./ / the CDN address
publicPath: '/',}}Copy the code
Here we have configured a single entry, and the output is bundle.js; If there are Multiple entries, this will not work. Webpack will prompt Conflict: Multiple chunks emit assets to the same filename. Webpack provides placeholders to ensure that each output file has a unique name:
module.exports = {
entry: {
home: './src/home.js'.list: './src/list.js'.detail: ['./src/detail.js'.'./src/common.js'],},output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].bundle.js',}}Copy the code
The webPack package is then packaged into three different bundles according to the name of the entry file; There are also the following different placeholder strings:
A placeholder | describe |
---|---|
[hash] | Hash of the module identifier |
[chunkhash] | Hash of chunk content |
[name] | The name of the module |
[id] | Module identifier |
[query] | The module’s query, for example, filename? The following string |
Module (Chunk) Bundle (Chunk) Module (Chunk) Bundle (Chunk) Module exports are common in our code, such as module.exports. Chunk usually appears with entry, and Bundle always appears with output.
- Module: We write source code, whether commonJS or AMdJS, can be understood as a module
- Chunk: When the module source files we wrote are sent to Webpack for packaging, Webpack will generate chunk files based on the file reference relationship. Webpack will perform some operations on these chunk files
- Bundle: After processing the chunk files, webpack finally outputs the bundle file. This bundle file contains the final source file that has been loaded and compiled, so it can be run directly in the browser.
Let’s take a closer look at these three concepts in the following diagram:
Conclusion:
Module, chunk, and bundle are the same logical code with three names in different transformation scenarios: module is written directly, chunk is processed by Webpack, and bundle can be run directly by the browser.
Hash, chunkhash, contenthash
Now that you understand the concept of chunk, it is easy to understand the difference between chunkhash and hash in the table above.
- Hash: Is related to the construction of the entire project. Whenever a file changes in the project, the hash value of the entire project will change and all files will share the same hash value.
- Chunkhash: it is related to the construction of the import file. The corresponding chunk is constructed based on the import file and the hash for each chunk is generated. When the entry file changes, the hash value of the corresponding chunk changes.
- Contenthash: Creates a unique hash based on the content of the file. That is, when the content of the file changes, the hash changes.
model
In Webpack2 and Webpack3, we need to manually add plug-ins for code compression, the definition of environment variables, but also need to pay attention to the judgment of the environment, very tedious; The mode configuration is provided directly in webpack4 and can be used out of the box. Webpack also warns if configuration is ignored.
module.exports = {
mode: 'development'};/ / equivalent to
module.exports = {
devtool:'eval'.plugins: [
new webpack.NamedModulesPlugin(),
new webpack.NamedChunksPlugin(),
new webpack.DefinePlugin({
"process.env.NODE_ENV": JSON.stringify("development")]}})Copy the code
The development mode tells WebPack that I am now in development mode, which means that the packaged content should be development-friendly, easy to debug and enable real-time browser updates.
module.exports = {
mode: 'production'};/ / equivalent to
module.exports = {
plugins: [
new UglifyJsPlugin(/ *... * /),
new webpack.DefinePlugin({
"process.env.NODE_ENV": JSON.stringify("production")}),new webpack.optimize.ModuleConcatenationPlugin(),
new webpack.NoEmitOnErrorsPlugin()
]
}
Copy the code
Production mode is not development-friendly, just focused on packaging performance and generating smaller bundles. Don’t panic if you see a lot of plugins here, we’ll explain what they do.
Why do we use json.stringify (“production”) when defining environment variables in DefinePlugin? Would it be easier to use “production” instead?
Let’s first look at what json.stringify (“production”) generates; The result of the run is “”production””, notice that it’s not your eyes that are smudge or that there’s a little black dot on the screen, it’s actually one more set of quotes than “production”.
We can simply think of the DefinePlugin as replacing all the process.env.node_env in the code with the contents of the string. Suppose we have code in our code that determines the environment as follows:
//webpack.config.js
module.exports = {
plugins: [
new webpack.DefinePlugin({
"process.env.NODE_ENV": "production"]}}),//src/index.js
if (process.env.NODE_ENV === 'production') {
console.log('production');
}
Copy the code
The resulting code compiles like this:
//dist/bundle.js
The production variable is not defined in the code
if (production === 'production') {
console.log('production');
}
Copy the code
However, we may not have defined the production variable in our code, which will cause the code to report an error directly, so we need to wrap a layer with json.stringify:
//webpack.config.js
module.exports = {
plugins: [
new webpack.DefinePlugin({
//"process.env.NODE_ENV": JSON.stringify("production")
/ / equivalent to
"process.env.NODE_ENV": '"production"']}}),//dist/bundle.js
if ("production"= = ='production') {
console.log('production');
}
Copy the code
The compiled code should be fine.
Automatic page generation
In the above code, we found that we generated the index.html manually and then imported the packaged bundle. However, this would be too tedious. Moreover, if the generated bundle introduced hash values, the generated file name would be different each time, so we need a plug-in that generates HTML automatically. First we need to install this plugin:
npm install --save-dev html-webpack-plugin
Copy the code
In Demo3, we generated three different bundle.js files. We want to import these three files in three different pages. Modify the config file as follows:
module.exports = {
// omit other code
plugins: [
new HtmlWebpackPlugin({
// The referenced template file
template: './index.html'.// The generated HTML name
filename: 'home.html'.chunks: ['home']}),new HtmlWebpackPlugin({
template: './index.html'.filename: 'list.html'.chunks: ['list']}),new HtmlWebpackPlugin({
template: './index.html'.filename: 'detail.html'.chunks: ['detail']})]}Copy the code
Using index.html as the template file, we generated three different pages, home, List, and detail, and introduced different bundles through chunks. If there are no chunks, each page will import all the generated bundles.
The htML-webpack-plugin also supports the following fields:
new HtmlWebpackPlugin({
template: './index.html'.filename: 'all.html'.// Inject title into the page
title: 'html webpack plugin title'.// All chunks links are introduced by default
chunks: 'all'.// Inject the page location
inject: true./ / enable the hash
hash: true.favicon: ' '.// Insert meta tags
meta: {
'viewport': 'width = device - width, initial - scale = 1.0'
},
minify: {
// Clear the script tag quotes
removeAttributeQuotes: true.// Clear comments in HTML
removeComments: true.// Clear Spaces and newlines in HTML
// Compress the HTML into a single line
collapseWhitespace: false.// Compress the HTML inline style into a single line
minifyCSS: true.// Clear elements with empty content (use with caution)
removeEmptyElements: false.// Clear the type attribute of the style and link tags
removeStyleLinkTypeAttributes: false}}),Copy the code
After setting title above, you need to set the template string in the template file:
<title><% = htmlWebpackPlugin.options.title% ></title>
Copy the code
loader
Loader is used to convert the source code of the module module. By default, WebPack can only recognize commonJS code, but we will introduce files such as vue, TS, less in the code, webPack can not process it. Loader extends webPack’s ability to handle multiple file types and convert these files into JS and CSS that browsers can render.
Module. rules allows us to configure multiple loaders. We can clearly see which loaders are applied to the current file type, and the loader code is in Demo4.
{
module: {
rules: [{test: /\.js$/.use: {
loader: 'babel-loader'.options: {}}}, {test: /\.css$/.use: [{loader: 'style-loader' },
{ loader: 'css-loader'}]},]}}Copy the code
We can see that the rules property value is an array, and each array object represents a different matching rule; The test attribute is a regular expression that matches different file suffixes. Use indicates what loader to call to process the file. When there are multiple Loaders, use requires an array.
Multiple Loaders support chain transfer, which enables pipeline processing of resources. The return value of the previous loader is passed to the next loader. Loader processing has a priority, from right to left, from bottom to top; In the above demo, the CSS processing follows this priority, CSS-loader first, and then to style-loader; Therefore, we should pay attention to the sequence when writing loader.
CSS – loader and style – loader
Css-loader and style-loader have similar functions from their names. However, their functions are very different, but they are often used in pairs. Installation method:
npm i -D css-loader style-loader
Copy the code
Css-loader is used to interpret @import and URL (); Style-loader is used to insert the style sheet generated by CSS-loader into the page with the
/* /src/head.css */
.head{
display: flex;
background: # 666;
}
/* /src/foot.css */
.foot{
background: #ccc;
}
/* /src/index.css */
@import './head.css';
@import './foot.css';
.wrap {
background: # 999;
}
Copy the code
Add index. CSS to the entry file, and you can see the packaging effect. Insert three style tags in the page, and the code is in demo4:
Sass – loader and less – loader
These two loaders are used to handle sass and less styles. Installation method:
npm i -D sass-loader less-loader node-sass
Copy the code
Configure in config, code in demo4:
{
// Other configurations
rules: {
test: /\.scss$/.use: [{
loader: 'style-loader'
}, {
loader: 'css-loader'}, {loader: 'sass-loader'
}]
},{
test: /\.less$/.use: [{
loader: 'style-loader'
}, {
loader: 'css-loader'}, {loader: 'less-loader'}}}]Copy the code
postcss-loader
After 202 years, you don’t want to manually add -moz, -ms, -webkit and other browser private prefixes. Postcss provides many extensions to styles; Install without saying anything:
npm i -D postcss-loader
Copy the code
As usual, configure in config:
rules: [{
test: /\.scss$/.use: [{
loader: 'style-loader'
}, {
loader: 'css-loader'
}, {
loader: 'postcss-loader'}, {loader: 'sass-loader'
}]
},{
test: /\.less$/.use: [{
loader: 'style-loader'
}, {
loader: 'css-loader'
}, {
loader: 'postcss-loader'}, {loader: 'less-loader'}}]]Copy the code
As we excitedly packed to see the effect, found that the style is still the same, and what has not changed.
This is because postCSS has only two main functions: the first is to parse CSS into an abstract syntax tree AST that JS can manipulate, and the second is to call plug-ins to process the AST and get results. So postCSS is usually handled by plug-ins, not directly, so we need to install some plug-ins first:
npm i -D autoprefixer postcss-plugins-px2rem cssnano
Copy the code
Create a new.browserslistrc file in the project root directory.
> 0.25%
last 2 versions
Copy the code
We extract the postcss configuration separately to postcss.config.js in the project root directory:
module.exports = {
plugins: [
// Automatically add the prefix
require('autoprefixer'),
// The px is converted to REM and applied to the mobile terminal
require('postcss-plugins-px2rem') ({remUnit: 75 }),
// Optimize merging CSS
require('cssnano')]}Copy the code
With the Autoprefixer plug-in, our packaged CSS is automatically prefixed.
babel-loader
Many of you have experienced the pain of writing your JS code that doesn’t run on IE10 or IE11, and then trying to introduce various polyfills. Babel makes it easy for us to move from higher versions of ES6 or even ES7 to ES5; We’ll start by installing the dependencies required by Babel:
npm i -D babel-loader @babel/core @babel/preset-env @babel/plugin-transform-runtime
npm i -S @babel/runtime
Copy the code
Add loader to config to process js:
{
// Omit other configurations
rules: [{
test: /\.js/.use: {
loader: 'babel-loader'}}}]Copy the code
Similarly, we extract the Babel configuration to the root directory and create a new. Babelrc file:
{
"presets": [
"@babel/preset-env"]."plugins": [
"@babel/plugin-transform-runtime"]}Copy the code
We can try to write some ES6 syntax in index.js and see the code translated to ES5, which is in Demo4. Since babel-loader is slow in translation, we can see the time consumption of each loader after adding the time plug-in later. Babel-loader is the most time-consuming. So we’re going to use Babel as little as possible to translate files, we’re going to improve config,
{
// Omit other configurations
rules: [{
test: /\.js$/.use: {
loader: 'babel-loader'
},
// exclude: /node_modules/,
include: [path.resolve(__dirname, 'src')]}}]Copy the code
Use $on the re for exact matching, exclude files in node_modules, and include will only match files in SRC. Include is recommended because it has a narrower and more accurate scope than exclude.
File – loader and url – loader
Both file-loader and URl-loader are used to process files such as images, fonts and ICONS. The url-loader works in two cases: If the file size is smaller than limit, the url-loader converts the file to base-64 encoding to reduce HTTP requests. If the file size is larger than the limit parameter, file-loader is called to process the file. Therefore, we prefer to use url-loader and install it first. Before installing url-loader, we also need to install file-loader first:
npm i file-loader url-loader -D
Copy the code
Next, modify config:
{
// Omit other configurations
rules: [{
test: /\.(png|jpg|gif|jpeg|webp|svg|eot|ttf|woff|woff2)$/.use: {
loader: 'url-loader'.options: {
//10k
limit: 10240.// Generate the resource name
name: '[name].[hash:8].[ext]'.// The path to generate the resource
outputPath: 'imgs/'
},
exclude: /node_modules/,}}}]Copy the code
We add a centered background image of less than 10K to the body in the CSS:
body{
width: 100vw;
height: 100vh;
background: url(./bg.png) no-repeat;
background-size: 400px 400px;
background-position: center center;
}
Copy the code
When you look at the body style after packaging, you can see that the image has been replaced with a Base64 URL in Demo4.
html-withimg-loader
If we reference an image on the page, we will find that the packaged HTML still references the image in the SRC directory, which is obviously wrong, so we need a plug-in to process the HTML reference image:
npm i -D html-withimg-loader
Copy the code
The HTML is configured in config as usual:
{
// Omit other configurations
rules: [{
test: /\.(htm|html)$/.use: {
loader: 'html-withimg-loader'}}}]Copy the code
Goose, however, opened the page and found this:
This is because each image is treated as a module in url-loader. We also need to modify it in url-loader:
use: {
loader: 'url-loader'.options: {
//10k
limit: 10240.esModule: false}}Copy the code
So our image reference on the page is also modified, and the code is in Demo4.
note
HTML – withimg – loader can lead to HTML – webpack – plugin plug-in into the title of the template string < % = htmlWebpackPlugin. Options. The title % > failure, intact the display on the page; Therefore, if we want to keep both functions, we need to delete htMl-withimg-loader in config and reference the image as follows:
<img src="<%=require('./src/bg1.png') %>" alt="" srcset="">
Copy the code
vue-loader
Finally, a special vue-loader is used to process VUE files.
npm i -D vue-loader vue-template-compiler
npm i -S vue
Copy the code
Let’s start by creating a vue file in Demo5:
//src/App.vue <template> <div id="app"> <div class="box" @click="tap">{{title}}</div> </div> </template> <script> export Default {name: 'app', data(){return {title: 'app instance '}}, methods: { tap(){ this.title = this.title.split('').reverse().join('') } } } </script> <style> #app{ font-size: 16px; background: #ccc; } </style>Copy the code
Then reference it in the webpack entry file:
//src/main.js
import Vue from 'vue'
import App from './App.vue'
new Vue({
render: h= > h(App)
}).$mount('#app')
Copy the code
Vue loader is not the same as other loaders. In addition to binding it to a. Vue file, we also need to introduce a plug-in for it:
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
module: {
rules: [
// Omit other loaders
{
test: /\.vue$/.loader: 'vue-loader'}},plugins: [
new VueLoaderPlugin(),
]
}
Copy the code
So we can have fun writing vUE in code.
Setting up the development environment
In the demo above, we generated the DIST file using the command line package, and then opened the HTML directly or viewed the page through static-server. However, packaging every time we write code seriously affects the efficiency of development. We want to see the page immediately after we write the code. Webpack-dev-server provides a simple Web server that can be reloaded in real time.
First install dependencies in our project:
npm i -D webpack webpack-dev-server
Copy the code
The use of webpack-dev-server is the same as wepack, except that it starts an additional Express server. We will create a new webpack.dev.config.js configuration file in the project and configure the development environment separately. The relevant code is in Demo6:
module.exports = {
// Omit other configurations
devServer: {
// Start the server port
port: 9000.// The default is localhost, which can only be accessed locally
host: "0.0.0.0".// Automatically open the browser
open: false.// Enable module hot replacement
hot: true.// Enable gzip compression
compress: true
},
plugins: [
// Hot update plugin
new webpack.HotModuleReplacementPlugin({
})
]
}
Copy the code
Start the server with the command line webpack-dev-server. After starting the server, we find that the root directory does not generate any files because webpack is packaged in memory. The reason for not generating files is that accessing code in memory is faster than accessing code in files.
Public /index.html pages sometimes refer to static files in the local directory. If you open the page directly, you will find that the reference to these static files is invalid. You can modify the working directory of the server and specify multiple static directory:
contentBase: [
path.join(__dirname, "public"),
path.join(__dirname, "assets")]Copy the code
Hot Module Replacemen (HMR) is that after the code is modified and saved, Webpack repackages the code and sends the new Module to the browser. The browser replaces the old Module with the new Module, so that the page can be updated without refreshing the browser.
It can be seen that the browser and webpack-dev-server are connected through a Websock. During initialization, the client saves a packaged hash value. During each update, the server listens for file changes, generates the latest hash value and pushes it to the client through websocket again. The client compares the hash value twice and sends a request to the server to return the updated module file for replacement.
Let’s click on the number of lines next to the source code to see what the compiled source looks like:
It was originally a simple ADD function, but it was difficult to understand the meaning of the original code through the module encapsulation of Webpack. Therefore, we need to map the compiled code back to the source code. Different configurations of Devtool have different effects and speeds. After combining performance and quality, we usually use cheap-module-eval-source-map in development environment and source-Map in production environment.
module.exports = {
devtool: 'cheap-module-eval-source-map'.// Other configurations
}
Copy the code
Comparison of other modes:
plugins
We also introduced DefinePlugin, HtmlWebpackPlugin and other plugins above. We found that these plugins can affect the construction process of Webpack to varying degrees. There are also some commonly used plugins below, and the relevant code of plugins is in Demo7.
clean-webpack-plugin
Clean-webpack-plugin is used to clean up the bundle generated by the previous project before packaging. It automatically cleans the folder according to output.path. 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. This plugin is very easy to install and use:
npm i -D clean-webpack-plugin
Copy the code
After installation, we can configure it in config:
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
// Other configurations
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: './public/index.html'.filename: 'index.html',}})]Copy the code
mini-css-extract-plugin
Our previous styles were inserted into the page via style-loader, but the production environment requires a separate style file to be extracted. The Mini-CSs-extract-plugin can help me strip styles from JS:
npm i -D mini-css-extract-plugin
Copy the code
We use style-loader in development environment and mini-CSS-extract-plugin in production environment:
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
// Other configurations
module: {
rules: [{test: /\.less/.use: [{
loader: isDev ? 'style-loader' : MiniCssExtractPlugin.loader
},{
loader: 'css-loader'}, {loader: 'less-loader'}}}]],plugins: [
new MiniCssExtractPlugin({
filename: "[name].[hash:8].css",}})]Copy the code
After importing loader, we also need to configure plugin. The extracted CSS also supports the placeholder string in output.filename.
optimize-css-assets-webpack-plugin
We can find that although the production mode is configured, the packaged JS is compressed, but the packaged CSS is not compressed. In production we need to compress CSS:
npm i optimize-css-assets-webpack-plugin -D
Copy the code
And then also introducing plugins:
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
module.exports = {
// Other configurations
plugins: [
new OptimizeCSSAssetsPlugin(),
]
}
Copy the code
copy-webpack-plugin
As in Demo6, we introduced static resources in public/index.html, but webpack didn’t help us copy to the dist directory when we packed, so copy-webpack-plugin did a good job of copying for me
npm i -D copy-webpack-plugin
Copy the code
Configure the source and destination paths we need to copy in config:
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
plugins: [
new CopyWebpackPlugin({
patterns: [{from: 'public/js/*.js'.to: path.resolve(__dirname, 'dist'.'js'),
flatten: true,}]}),]}Copy the code
ProvidePlugin
ProvidePlugin can quickly load modules we want to introduce without requiring. JQuery import:
import $ from 'jquery'
$('.box').html('box')
Copy the code
But we can configure ProvidePlugin in config to use $without import:
module.exports = {
plugins: [
new webpack.ProvidePlugin({
$: 'jquery'.jQuery: 'jquery']}}),Copy the code
However, it would be confusing to introduce too many modules in a project without require, so I recommend loading some common ones like jQuery, Vue, Lodash, etc.
The difference between loader and plugin
With so many loaders and plugins introduced, let’s review the differences between them:
Loader: Since WebPack can only recognize JS, Loader acts as a translator to help WebPack preprocess the translation of other types of resources. Plugins: Plugins extend the functionality of WebPack by broadcasting many events while WebPack is running. Plugins can listen for these events and then change the output through the API provided by WebPack.
conclusion
Finally, this article is the foundation of Webpack, there are a lot of production environment optimization has not been written; So you look forward to optimization.
Reference:
Come again a dozen Webpack interview questions Webpack HMR principle analysis
For more front-end information, please pay attention to the public number [front-end reading].
If you think it’s good, check out my Nuggets page. Please visit Xie xiaofei’s blog for more articles