foreword
Hand-to-hand teach you how to pack, let you feel webpack in the hands-on practice process.
Before you start, you can briefly understand the concept of webpack
Each summary has a corresponding branch, which is convenient for everyone to learn
webpack version: 5.58.1
getting Started
Create a new directory and initialize npm
npm init
Next install the webpack and webpack-cli packages
npm i -D webpack webpack-cli
default allocation
Create a new folder src, create a new main.js in it, and write a little test code
console.log("webpack")
Add new commands to scripts in package.json
"scripts": { "build": "webpack ./src/main.js" },
Execute the packaging command npm run build
At this point, if a dist folder is generated and contains main.js inside, it means that the package has been successful
This example is just the default configuration of webpack itself. Next, we will implement a richer custom configuration.
custom configuration
Create a new build folder and create a new webpack.config.js in it
const path = require('path'); module.exports = { mode:'development', // development mode entry: path.resolve(__dirname,'../src/main.js'), // entry file output: { filename: 'output.js', // Packaged file name path: path.resolve(__dirname,'../dist') // packaged directory } }
Change packaging command
{ // ... "scripts": { "build": "webpack --config build/webpack.config.js" }, }
Then execute npm run build, you will get the following results
where main.js is the legacy we packaged for the first time.
js has been packaged, the next thing we have to do is to introduce js into the html file
add js to html file
We need html-webpack-plugin to do this for us
npm i -D html-webpack-plugin
Create a new folder public at the same level as build, and create a new index.html in it
The configuration is as follows
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin') module.exports = { mode:'development', // development mode entry: path.resolve(__dirname,'../src/main.js'), // entry file output: { filename: '[name].[hash:8].js', // [name] refers to the name of the entry attribute, the default is main path: path.resolve(__dirname,'../dist') // packaged directory }, plugins:[ new HtmlWebpackPlugin({ // Select an html as a template, the same html will be generated in the dist directory, and then the packaged js will be injected into the html file template: path.resolve(__dirname,'../public/index.html') }) ] }
After the packaging is successful, check whether the index.html file in the dist directory refers to the packaged js
How to inject multiple files into html
- Multiple entry files, injected into the same html file
In this case, we just need to add the entry, and the html-webpack-plugin plugin will automatically inject all packaged js into html
module.exports = { // ... entry: { main: path.resolve(__dirname,'../src/main.js'), share: path.resolve(__dirname,'../src/share.js') } }
- Multiple entry files, injected into different html files according to different requirements
We can fix this by generating multiple instances of html-webpack-plugin
module.exports = { // ... plugins:[ new HtmlWebpackPlugin({ // Select an html as a template, the same html will be generated in the dist directory, and then the packaged js will be injected into the html file template: path.resolve(__dirname,'../public/index.html'), filename: 'index.html', chunks: ['main'] // Configure which files will be injected into the html file. [] means no js will be injected. If there is no such attribute, all js will be injected by default. }), new HtmlWebpackPlugin({ template: path.resolve(__dirname,'../public/share.html'), filename: 'share.html', chunks: ['share'] }) ] }
Empty the dist directory before packaging
I believe you have also discovered that there are more and more files in the dist directory. Let's solve this problem.
We need clean-webpack-plugin to do this for us
npm i -D clean-webpack-plugin
// The rest of the configuration is the same as above const { CleanWebpackPlugin } = require('clean-webpack-plugin') module.exports = { plugins:[ // ... new CleanWebpackPlugin() ] }
As reminded by friends, webpack5 has a new way to clear the dist directory, and the clean field is added to the output, which is now added below
module.exports = { // ... output: { filename: '[name].[hash:8].js', // [name] refers to the name of the entry attribute, the default is main path: path.resolve(__dirname,'../dist'), // packaged directory clean: true }, }
Inject css into html as style tag
Our entry file is js, so we introduce our css file in entry js
// main.js import "../static/css/base.css" import "../static/css/color.scss" import "../static/css/fontsize.less" console.log("webpack")
We need some loader s to parse our css files
npm i -D style-loader css-loader
If you use less to build styles, you need to install
npm i -D less less-loader
If you use scss to build styles, you need to install
npm i -D node-sass sass-loader
The configuration file is as follows
module.exports = { // ... module: { rules: [ { test: /\.css$/, use: ["style-loader", "css-loader"] // Parsing from right to left }, { test: /\.scss$/, use: ["style-loader", "css-loader", "sass-loader"] // In addition, you need to install node-sass(sass also works) }, { test:/\.less$/, use:['style-loader','css-loader','less-loader'] // In addition, you need to install the less module } ] } }
After packaging, open the html file in the browser, and you can see the css we injected
add browser prefix to css
In order to adapt to more browser styles we need to prefix css
We need postcss-loader and autoprefixer to do this for us
Refer to the webpack video explanation: into learning
There are two ways to introduce autoprefixer
- Introduction of postcss.config.js (recommended)
Create postcss.config.js in the **project root directory**, the configuration is as follows
module.exports = { plugins: [ require('autoprefixer') ] }
Then import it directly in webpack.config.js
module.exports = { // ... module: { rules: [ { test: /\.css$/, use: ["style-loader", "css-loader", "postcss-loader"] // Parsing from right to left }, { test: /\.scss$/, use: ["style-loader", "css-loader", "postcss-loader", "sass-loader"] // In addition, you need to install node-sass(sass also works) }, { test:/\.less$/, use:['style-loader','css-loader', "postcss-loader", 'less-loader'] // In addition, you need to install the less module } ] } }
- Configure directly in webpack.config.js
moudule.exports = { // ... module: { rules: [ { test: /\.css$/, use: ["style-loader", "css-loader", { loader: "postcss-loader", options: { postcssOptions: { plugins: [ ['autoprefixer'] ] } } }] // Parsing from right to left }, { test: /\.scss$/, use: ["style-loader", "css-loader", { loader: "postcss-loader", options: { postcssOptions: { plugins: [ ['autoprefixer'] ] } } }, "sass-loader"] // In addition, you need to install node-sass(sass also works) }, { test:/\.less$/, use:['style-loader','css-loader', { loader: "postcss-loader", options: { postcssOptions: { plugins: [ ['autoprefixer'] ] } } }, 'less-loader'] // In addition, you need to install the less module } ] } }
After completing the above configuration, we found that css was not successfully prefixed. Here we have to do another step, that is to configure package.json, and add the following configuration to package.json
{ // ... "browserslist": [ "defaults", "not ie < 11", "last 2 versions", "> 1%", "iOS 7", "last 3 iOS versions" ] }
External links import css files
Above, we load our styles through the style tag, but if there are too many css files, it will be very confusing.
We need mini-css-extract-plugin to help us implement
npm i -D mini-css-extract-plugin
// The rest of the configuration remains the same const MiniCssExtractPlugin = require("mini-css-extract-plugin"); module.exports = { // ... plugins: [ // ... new MiniCssExtractPlugin({ filename: "[name].[hash].css", }) ], module: { rules: [ { test: /\.css$/, use: [MiniCssExtractPlugin.loader, "css-loader", "postcss-loader"] // Parsing from right to left }, { test: /\.scss$/, use: [MiniCssExtractPlugin.loader, "css-loader", { loader: "postcss-loader", options: { postcssOptions: { plugins: [ ['autoprefixer'] ] } } }, "sass-loader"] // In addition, you need to install node-sass(sass also works) }, { test:/\.less$/, use:[MiniCssExtractPlugin.loader,'css-loader', "postcss-loader", 'less-loader'] // In addition, you need to install the less module } ] } }
However, in this way, all css will be merged into one css file. If you want to split it, you can only use other methods. I see that others use extract-text-webpack-plugin on the Internet, but when I go to the npm official website to see Time.
So I won't discuss splitting css here.
image processing
Image processing in css and js only needs to add the following configuration
module.exports = { // ... module: { rules: [ // ... { test: /\.(jpe?g|png|gif)$/i, type: "asset", generator: { filename: 'static/[name].[hash].[ext]' } }, ] } }
If you need to process pictures in html, you need to use html-loader
npm i -D html-loader
The configuration is as follows
module.exports = { // ... module: { rules: [ // ... { test: /\.html$/i, loader: "html-loader" }, ] } }
If you need to configure more resource files, please refer to the resource module
escape js file
In order to make our js code compatible with more environments we need to escape our js files
npm i -D babel-loader @babel/preset-env @babel/core core-js
module.expors = { // ... module: { rules: [ // ... { test: /\.js$/, use: { loader: 'babel-loader', options: { presets: [ [ '@babel/preset-env', { useBuiltIns: 'usage', corejs: { //version of core-js version: 3 }, //Compatible browser required targets: { chrome: '60', firefox: '60', ie: '9', safari: '10', edge: '17' } } ] ], } }, exclude: /node_modules/ } ] } }
babel-loader is responsible for converting ES6/7/8 syntax to ES5 syntax
core-js is responsible for converting new APIs, such as promise s, Generator s, Set s, Maps, Proxy, etc.
Advanced
Build a Vue development environment
Vue file handling
Install the necessary dependencies first
npm i -D vue-loader vue-template-compiler vue-style-loader
npm i -S vue
vue-loader is used to parse .vue files
vue-template-compiler for compiling templates
vue-style-loader parsing styles
const vueLoaderPlugin = require('vue-loader/lib/plugin') module.exports = { // ... module:{ rules:[ // This loader must be placed at the top { test:/\.vue$/, use:['vue-loader'] } // ... ] }, resolve:{ // set path alias alias:{ 'vue$':'vue/dist/vue.runtime.esm.js', '@':path.resolve(__dirname,'../src') }, // Try to resolve these suffix names in order. // If there are multiple files with the same name but different suffixes, webpack will parse the file with the suffix listed first in the array and skip the rest. extensions:['*','.js','.json','.vue'] }, plugins:[ new vueLoaderPlugin() ] }
Hot update configuration
We need to use webpack-dev-server to start a local service and configure hot updates
npm i -D webpack-dev-server
The configuration is as follows
const Webpack = require('webpack') module.exports = { // ... devServer:{ port:3000, hot:true }, plugins:[ new Webpack.HotModuleReplacementPlugin() ] }
Configure packaging commands
"scripts": { // ... "dev": "webpack-dev-server --config build/webpack.config.js --open" },
Add --open to automatically open the http://localhost:3000 page
Next, write a few lines of code to test, first modify our main.js
// main.js import Vue from 'vue' import App from './App.vue' new Vue({ render: h => h(App) }).$mount('#app')
Create a new App.vue file
<template> <div> {{msg}} </div> </template> <script> export default { data() { return { msg: "webpack vue" } }} </script> <style lang='scss' scoped> div { color: aquamarine; display: flex;} </style>
Modify the original index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>webpack</title> </head> <body> <div id="app"></div> </body> </html>
Finally execute npm run dev
Distinguish between development and production environments
There is a huge difference in build targets between development and production environments. In the development environment, we need: a powerful source map and a localhost server with live reloading (real-time reloading) or hot module replacement (hot module replacement) capabilities. The production environment goals have shifted to other areas, focusing on compressing bundle s, lighter source map s, resource optimization, etc., through these optimizations to improve load times. Because of the logical separation to follow, we generally recommend writing separate webpack configs for each environment.
We add two more files webpack.prod.js and webpack.dev.js based on the original webpack.config.js
Here we need to use webpack-merge to help us merge the code
npm i -D webpack-merge
// webpack.dev.js const { merge } = require('webpack-merge'); const common = require('./webpack.config.js') module.exports = merge(common, { mode: 'development', devtool: 'inline-source-map', devServer:{ port:3000, hot:true } });
// webpack.prod.js const { merge } = require('webpack-merge'); const common = require('./webpack.config.js'); module.exports = merge(common, { mode: 'production', });
The original webpack.config.js also needs to be modified, we only need to delete the mode and devserver fields
Finally modify the scripts command in package.json
"scripts": { "build": "webpack --config build/webpack.prod.js", "dev": "webpack-dev-server --config build/webpack.dev.js --open" },
Run npm run dev in the development environment, package npm run build
at last
It's not easy to code words, if it helps you, then give it a like