preface
This article is a continuation of the previous one, “WebPack4 Builds a VUE project development Environment from scratch.” I highly recommend reading an article first.
This article mainly describes the differences between different environments and some points that can be optimized
The article demo has been submitted to Github, please download ———— “Webpack 4 Demo”
Distinguish between “development environment” and “Production Environment”
- Development environment:
Hot update
,multithreading
,sourceMap
, etc. - Production environment:
Js compressed
,Extract the CSS
,CSS compression
,multithreading
,sourceMap
,Directory cleaning
, etc.
Because the requirements of the “development environment” and the “production environment” are different, we build our projects in different environments.
configurationwebpack.common.js
、webpack.dev.js
和 webpack.prod.js
Create a new build directory and create the following three files
webpack.common.js
Common configurationwebpack.dev.js
Development Environment Configurationwebpack.prod.js
Generate environment configuration
The installationwebpack-merge
Used to merge the WebPack common configuration into the specified environment
NPM [email protected] - I DCopy the code
configurationwebpack.common.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = {
entry: path.join(__dirname, ".. /src/main.js"),
output: {
path: path.join(__dirname, ".. /dist"),
filename: "bundle.js"
},
module: {
rules: [{test: /\.(png|jpg|gif)$/i,
use: [
{
loader: 'url-loader'.options: {
limit: 8192.// If the value is less than 8K, use URl-loader to convert to base64, otherwise use file-loader to process the file
fallback: {
loader: 'file-loader'.options: {
name: '[name].[hash:8].[ext]'.outputPath: '.. /dist/images/'.// The path where the files are stored after packaging, dist/images}},}}]}, {test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\? . *)? $/,
use: [
{
loader: 'url-loader'.options: {
limit: 8192.fallback: {
loader: 'file-loader'.options: {
name: '[name].[hash:8].[ext]'.outputPath: '.. /dist/media/',}},}}]}, {test: /\.(woff2? |eot|ttf|otf)(\? . *)? $/i,
use: [
{
loader: 'url-loader'.options: {
limit: 1.fallback: {
loader: 'file-loader'.options: {
name: '[name].[hash:8].[ext]'.outputPath: '.. /dist/fonts/',}},}}]}, {test: /\.(css)$/,
use: [
"style-loader"."css-loader"."postcss-loader"] {},test: /\.(less)$/,
use: [
"style-loader"."css-loader"."postcss-loader"."less-loader",]}, {test: /\.vue$/,
use: ["vue-loader"]]}},plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, '.. /src/index.html')}),new VueLoaderPlugin()
]
};
Copy the code
configurationwebpack.dev.js
const webpack = require("webpack");
const { merge } = require('webpack-merge')
const webpackCommon = require('./webpack.common.js')
module.exports = merge(webpackCommon, {
mode: "development".devServer: {
contentBase: path.join(__dirname, ".. /dist"),
compress: true.open: true.quiet: false.hot: true.// Start hot update
port: 3000.clientLogLevel: 'none'.// Close the hot update output from the browser console
},
plugins: [
new webpack.HotModuleReplacementPlugin()
]
});
Copy the code
configurationwebpack.prod.js
const { merge } = require('webpack-merge')
const webpackCommon = require('./webpack.common.js')
module.exports = merge(webpackCommon, {
mode: "production"
})
Copy the code
Modify thepackage.json
NPM script
Specify that webPack executes different configuration files for different environments.
"Scripts ": {"serve": "webpack-dev-server --config build/webpack.dev.js", // "Webpack --config build/webpack.prod.js",// development environment},Copy the code
It is also possible to set process.env.node_env using –mode and execute different configuration file contents depending on whether the environment is “development” or “production”. I won’t do it here. There are also many examples on the Internet, interested in their own search ah
CleanWebpackPlugin automatically removes dist’s last packaged content
npm i clean-webpack-plugin -D
Copy the code
// webpack.prod.js
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
plugins: [
new CleanWebpackPlugin()
],
Copy the code
DefinePlugin sets the environment global variables
DefinePlugin is a built-in webPack plugin that does not need to be installed
configurationwebpack.dev.js
和 webpack.prod.js
Only webpack.dev.js is demonstrated here, and the webpack.prod.js Settings are the same.
Plugins: [new webpack.defineplugin ({'process.env': {// set global variables to call BASE_URL throughout the project: JSON.stringify('http://localhost:3000/dev') } }) ]Copy the code
Calling global variables
console.log('BASE_URL:', process.env.BASE_URL)
Copy the code
Set up thesourceMap
Easy to debug
Bundle.js that is packaged by WebPack is compressed. Can’t debug properly. SourceMap is for debugging. If you’ve used vue-cli before, when you package it, you’ll have a.map file in the dist directory, which is the source mapping file.
We can set devTool to generate different types of sourceMap. Different patterns generate different code volumes, build speeds, security, and so on. See the webPack website.
Personal recommendation, the development environment recommends using the eval generation mode, it will be faster. As for cheap and Module, you can choose according to your own needs. For production environments, it is recommended to place sourceMap locally or on the Intranet for security purposes. This can be configured using the SourceMapDevToolPlugin.
- The development environment
devtool: "cheap-module-eval-source-map", Copy the code
- The production environment
When using SourceMapDevToolPlugin, you need to set devtool: false. When using SourceMapDevToolPlugin, you need to set devtool: false.
//# sourceMappingURL= sourcemaps file path to the source code. When using browser debugging (F12), It will automatically look for the sourceMap for the path. We can customize this path in Append to support urls and local addresses
// webpack.prod.js
devtool: false.plugins: [
// By default, the generated schema is' source-map '
new webpack.SourceMapDevToolPlugin({
//sourcemap Indicates the Intranet address
append: '\n//# sourceMappingURL=http://localhost:1888/sourcemaps/[name].[hash:8].map'.// Generate the sourcemap directory and name
filename: 'sourcemaps/[name].[hash:8].map'.// Module :true // Equivalent to devtool module
// Columns :false //
// noSources:true // Equivalent to devtool noSources})].Copy the code
By the way, the vue-CLI “production environment” is generated as: devtool:source-map by default, which means the map file generated contains the uncompressed source code. The build speed is also extremely slow if the project is beating up
If you’re new to sourceMap, you may be confused, but the following article should help you
SourceMap recommends reading articles:
- JavaScript Source Map
- “What the hell are the seven SourceMap modes in DevTool?”
- “What You Don’t know about sourceMap”
Optimization (Preface)
Whether a project needs to be optimized, according to their own project situation to decide. For example, certain optimizations are only useful for large projects, but can be counterproductive for small projects. If you feel your build speed and project size are acceptable, there is no need to optimize.
Here are some points that can be optimized, but don’t add them all. According to their own project situation to try and choose, view the effect
Optimize pre-preparation
speed-measure-webpack-plugin
For viewingloader
和 The plug-in
Processing time of
webpack-bundle-analyzer
Use to view the size of the package after packaging.
Reduced file search scope
Specifies the loader processing range ———— exclude/include
Exclude is to exclude from looking in a directory
Include is the limit to what directory to look in
If the value of exclude is configured, the priority of exclude is higher than that of include. You are advised to use include only.
// webpack.commom.js
{
test: /\.js$/.// exclude: /node_modules/,
include: path.join(__dirname, ".. /src"),
use: ["babel-loader"]},Copy the code
Resolve. alias Alias configuration
Use aliases instead, write more concise, can also play a role in reducing the scope of the search
// webpack.commom.js
resolve: {
alias: {
"@": path.join(__dirname, ".. /src")}},Copy the code
Resolw. extensions specifies the file suffix matching rule
Webpack is set to Extensions: [‘.js’, ‘.json’] by default, assuming the file is imported without a suffix, it will match this rule.
For example: import router from “@/router/index”, look for js first, then json.
Extensions can change the order of the match. You can jump to its priority. Files that are not commonly used are not recommended
// webpack.commom.js
resolve: {
extensions: [".js".".vue".".json"]
/ / extensions: [", "js" ts ", "vue", "json"] if you have used to project ` typescript ` recommends `. Ts ` in front
}
Copy the code
The cache
cache-loader
Cache-loader is used in front of some loaders with high overhead. Loaders with low overhead do not need to be used. It will cache the results to disk, node_modueles/.cache/cache-loader default directory. The first build will take longer, and later builds will be faster
npm install cache-loader -D
Copy the code
// webpack.commom.js
{
test: /\.js$/,
include: path.join(__dirname, ".. /src"),
use: ["cache-loader"."babel-loader"]}Copy the code
babel-loader
In fact, Babel-Loader has its own caching function. I heard that cache-loader is a little faster. I have tried it myself and it is not much difference, cache-loader is slightly faster.
// webpack.commom.js
{
test: /\.js$/,
include: path.join(__dirname, ".. /src"),
use: [{
loader: 'babel-loader'.options: {
cacheDirectory: true}}},Copy the code
hard-source-webpack-plugin
HardSourceWebpackPlugin provides an intermediate cache for modules that take normal time to build for the first time. The second build is 60% to 90% faster. Use of DllPlugin and DllReferencePlugin together is not recommended
Note: When using HardSourceWebpackPlugin, do not use speed-measure-webpack-plugin, which will cause an error
npm install hard-source-webpack-plugin -D
Copy the code
// webpack.commom.js
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin');
plugins: [
// Provides an intermediate cache for modules that cannot be used with the SpeedMeasurePlugin plug-in
new HardSourceWebpackPlugin(),
// Exclude the MiniCssExtractPlugin from caching, otherwise an error will be reported
new HardSourceWebpackPlugin.ExcludeModulePlugin([
{
test: /mini-css-extract-plugin[\\/]dist[\\/]loader/,},]),]Copy the code
multithreading
As we all know that JavaScript is single-threaded, we can use Web Workers to execute JavaScript in real time with multiple threads. If you haven’t heard of the Web Worker, check out the article “Web Worker Tutorial”.
When building a project with WebPack, we can also use worker. There are two worker-based plug-ins, thread-Loader and happypack. Happypack seems to have been abandoned by the author, and thread-loader is recommended.
Please only use it on the loader that takes a long time!
npm install thread-loader -D
Copy the code
// webpack.commom.js
{
test: /\.js$/,
include: path.join(__dirname, ".. /src"),
use: ["thread-loader"."cache-loader"."babel-loader"]
// Loader takes a long time when the project is large
}
Copy the code
The compression
JS compression, remove comments andconsole
–terser-webpack-plugin
Webpack 4 requires installation and WebPack 5 is supported by default
npm i terser-webpack-plugin@4 -D
Copy the code
// webpack.prod.js
const TerserPlugin = require('terser-webpack-plugin');
optimization: {
minimizer: [
JS / / compression
new TerserPlugin({
parallel: true.// Enable multithreading
// include: path.join(__dirname, ".. /src"),
sourceMap: true.// Set this to true if SourceMapDevToolPlugin is used
extractComments: false.// The default package will generate a LICENSE. TXT file, set here to disable the generation
terserOptions: {
output: {
comments: false.// Delete comments
},
compress: {
drop_console: true / / remove the console
// drop_debugger: false // Default to true, debugger will be deleted},},}),],},Copy the code
CSS extract
If the generated JS package is too large, extracting CSS will help reduce the size of JS and render the page quickly (link introduces styles without blocking DOM and JS rendering).
NPM [email protected] - I DCopy the code
// webpack.prod.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module: {
rules: [{test: /\.(css)$/,
include: path.join(__dirname, ".. /src"),
use: [
MiniCssExtractPlugin.loader,
// "thread-loader", // if the project is large, the loader will take a long time to use
"css-loader"."postcss-loader"] {},test: /\.(less)$/,
include: path.join(__dirname, ".. /src"),
use: [
MiniCssExtractPlugin.loader,
// "thread-loader", // if the project is large, the loader will take a long time to use
"css-loader"."postcss-loader"."less-loader",]},]},/ / CSS
plugins: [
new MiniCssExtractPlugin({
filename: 'css/[name].[hash:8].css'}),]Copy the code
CSS compression
The goal is to reduce the volume of the project
npm i optimize-css-assets-webpack-plugin -D
Copy the code
// webpack.prod.js const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin'); Plugins: [// Compress CSS new OptimizeCssAssetsPlugin()]Copy the code
Reduce packaging
Tree Shaking
Tree Shaking is used to weed out code that was introduced but not used.
"SideEffects ": ["*.css", "*.vue"], "sideEffects": ["*.css", "*.vue"]Copy the code
externals
When packaging, eliminate these externals configured packages to reduce the volume. These packages are then introduced using a CDN.
// webpack.prod.js
externals: {
"vue": "Vue"."vue-router":"VueRouter"
}
Copy the code
<! -- index.html -->
<! -- CDN introduces dependencies excluded by externals -->
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.runtime.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/vue-router/3.5.2/vue-router.min.js"></script>
Copy the code
Rely on the version
As the latest version is WebPack 5, some plug-ins will also be updated synchronously, and the latest version of plug-ins is not applicable to WebPack 4, please refer to the following dependent version for installation!
"devDependencies": {
"@babel/core": "^ 7.4.4." "."@babel/preset-env": "^ 7.14.8"."autoprefixer": "^ 10.3.1"."babel-loader": "^ 8.2.2"."cache-loader": "^ 4.1.0." "."clean-webpack-plugin": "^ 3.0.0"."css-loader": "^ 5.2.7." "."file-loader": "^ 6.2.0"."hard-source-webpack-plugin": "^ 0.13.1." "."html-webpack-plugin": "^ 4.5.2." "."less": "^ 3.5.0." "."less-loader": "^ 7.3.0"."mini-css-extract-plugin": "^ 1.6.2"."optimize-css-assets-webpack-plugin": "^ the 6.0.1." "."postcss-loader": "^ 4.3.0"."speed-measure-webpack-plugin": "^ 1.5.0." "."style-loader": "^ 2.0.0." "."terser-webpack-plugin": "^ holdings"."thread-loader": "^ 3.0.4"."url-loader": "^ 4.4.1"."vue-loader": "^ 15.9.6"."vue-template-compiler": "^ 2.6.14"."webpack": "^ 4.46.0"."webpack-cli": "^ 3.3.11." "."webpack-dev-server": "^ 3.11.2"."webpack-merge": "^ 5.8.0"
},
Copy the code
The article demo has been submitted to Github, please download ———— “Webpack 4 Demo”
Feel good remember “like”! thank you