I haven’t written a blog for a long time since I started working. Time was divided into pieces, accumulated a period of learning results, just write this blog.

I have written Webpack4 articles before, but they are not very basic. The only actual combat article — build React development environment based on Webpack is also relatively simple, and does not involve CSS extraction, third-party library packaging and other functions. This article is relatively in-depth. However, due to the author’s limited level, there are inevitably fallacies, we welcome you to correct.

There is no entry of children’s shoes can refer to my previous article:

  • Shallow in and shallow out webpack
  • Build React development environment based on Webpack

Initialize the project

On the command line, type the following command:

mkdir Webpack-Vue && cd Webpack-Vue && npm init -y
Copy the code

You will then see a folder called webpack-vue in your current path with a package.json file containing default information. Open and modify some of the contents of this file.

Then we create the following folders in the project folder:

  • dist
  • The SRC, SRC/components
  • build

In Linux, you can type the following command for a quick creation:

mkdir src src/components dist build -p
Copy the code

Dist is used to store Webpack packaged project files, SRC is used to store your source code files, and Build is used to store Webpack package-related configuration files.

Under SRC, create the entry file index.js.

Commands created under Linux:

touch ./src/index.js
Copy the code

Create an index. HTML file in the root directory with the following contents:

<! DOCTYPE html> <html> <head> <title>Webpack Vue Demo</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta name="viewport" content="width=device-width, Initial - scale = 1.0 "> < / head > < body > < div id =" app "> < / div > < / body > < / HTML >Copy the code

This will be used as a template for our application, and the packaged JS file will be inserted into this file under the processing of the Webpack plug-in.

Other configuration files are added to suit your preferences, such as.gitignore files.

Install Webpack

To use Webpack, the first step is, of course, installation. Use the following command to install:

npm i webpack webpack-cli -D
Copy the code

You should then see a node_modules folder in your project folder and a devDependencies property in your package.json file. It contains the dependency name and version of the installation, and for now there are only Webpack and Webpack-CLI.

Configure the most basic Webpack

In this section we will start to configure a project with minimal packaging, starting with SRC /index.js.

In order to make the project structure more scientific, we put all Webpack configuration related files in the Build directory.

Go to the Build folder and create the following files:

  • webpack.base.conf.js
  • webpack.dev.conf.js
  • webpack.prod.conf.js
  • build.js

On Linux, you can type the following command to quickly create:

cd build/ && touch webpack.base.conf.js webpack.dev.conf.js webpack.prod.conf.js build.js
Copy the code

Of these, webpack.base.conf.js is the most basic packaging configuration, which is used by both development and production environments. Webpack.dev.conf.js is the configuration to use in the development environment. Webpack.prod.conf.js is the configuration to use in production. Build. js is a script packaged through the Node interface.

Next we write the most basic configuration information in the corresponding file.

(1) webpack. Base. Conf. Js

Write the basic configuration information first:

const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: { bundle: path.resolve(__dirname, '.. /src/index.js') }, output: { path: path.resolve(__dirname, '.. /dist'), filename: '[name].[hash].js' }, module: { rules: [ ] }, plugins: [ new HtmlWebpackPlugin({ template: path.resolve(__dirname, '../index.html') }) ] };Copy the code

(2) webpack. Dev. Conf. Js

Also write the most basic configuration information:

const merge = require('webpack-merge'); const path = require('path'); const baseConfig = require('./webpack.base.conf'); module.exports = merge(baseConfig, { mode: 'development', devtool: 'inline-source-map', devServer: { contentBase: path.resolve(__dirname, '.. /dist'), open: true } });Copy the code

(3) webpack. Prod. Conf. Js

In the following configuration, the CleanWebpackPlugin is written in 1.x.x version. After upgrading to 2.x.x, the constructor is written in a different way. Please refer to the cleanwebpack-plugin for details.

Continue writing the most basic configuration:

const merge = require('webpack-merge');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const path = require('path');
const baseConfig = require('./webpack.base.conf');
module.exports = merge(baseConfig, {
  mode: 'production',
  devtool: 'source-map',
  module: {
    rules: []
  },
  plugins: [
    new CleanWebpackPlugin(['dist/'], {
      root: path.resolve(__dirname, '../'),
      verbose: true,
      dry: false
    })
  ]
});
Copy the code

Note that we have referenced two new dependencies that need to be installed before they can be used:

cnpm i webpack-merge clean-webpack-plugin webpack-dev-server html-webpack-plugin -D
Copy the code

(4) build.js

This script is used to build the production environment based on Webpack-dev-server.

Next, we write our packaging script, which is packaged via Node’s call to Webpack.

const webpack = require('webpack'); const config = require('./webpack.prod.conf'); Webpack (config, (err, stats) = > {the if (err | | stats. HasErrors ()) {/ / processing error console. Here the error (err); return; } // Complete console.log(stats.tostring ({chunks: false, // make the build process more silent without output colors: true // show colors on console}); });Copy the code

The advantage of this is that you can do other things with Node, and it’s easy to call the Webpack configuration file when it’s not at the root of the project folder.

(5) NPM Scripts

Configuring NPM scripts makes it easier to use the package command.

In the scripts property of the package.json file, write the following two:

"build": "node build/build.js",
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js"
Copy the code

Now that the basic configuration is complete, we can test the packaging effect by writing the following code in SRC /index.js:

console.log('index.js! ');Copy the code

Then on the command line type:

npm run dev
Copy the code

On the page that opens automatically, I open the console and we see that the output is “index.js”, as expected.

Then enter the build command to build:

npm run build
Copy the code

Screenshot below:

This means that the packaging is successful, but we have only completed the basic packaging function, Vue is not yet available, we will make the project more powerful.

Introduce some basic loaders

To facilitate development, we need to introduce some loaders to simplify our writing and make our code compatible with more environments.

This section can be written from the Webpack documentation, as it is basic and not difficult to configure.

(1) the Babel – loader

To make our JavaScript code compatible with more environments, we need to use babel-Loader.

Configuration method:

First install babel-loader, babel-env, and babel-core. Note that if your babel-loader is 7.x, your babel-core must be 6.x; If your babel-loader is 8.x, your babel-core must be 7.x. If not, Webpack will report an error.

The installation command is as follows:

npm i babel-loader@7 babel-core babel-preset-env -D
Copy the code

Then add the following objects to the module.rules of webpack.base.conf.js:

{
  test: /\.js$/,
  use: 'babel-loader',
  exclude: /node_modules/
}
Copy the code

We also need to add a configuration file (.babelrc) in the root directory:

{
  "presets": [
    ["env", {
      "modules": false,
      "targets": {
        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
      }
    }]
  ]
}
Copy the code

This is what babel-preset-env is for to help us configure Babel. All we need to do is tell it what we want to be compatible with (the target runtime environment), and it will automatically convert the code to be compatible with the corresponding environment.

The above code indicates that we require the code to be compatible with the latest two versions of browsers, not IE 8, and also with more than 1% of the market.

Wouldn’t it be nice to just tell babel-preset-env you want a compatible environment and it will preset automatically? You don’t have to configure so much anymore.

Now let’s try to rewrite SRC /index.js as:

const x = 'index.js';

const y = (x) => {
  console.log(x);
}

y(x);
Copy the code

Then use NPM run build to package the package.

var x = 'index.js';

var y = function y(x) {
  console.log(x);
};

y(x);
Copy the code

This indicates that our code has been successfully converted.

For comparison, when Babel is not configured, the conversion results are as follows:

const x = 'index.js';

const y = (x) => {
  console.log(x);
}

y(x);
Copy the code

(2) the file – loader

This is used to modularize font files and image files.

Install file-loader:

npm i file-loader -D
Copy the code

Then add the following configuration to module.rules in webpack.base.conf.js:

{
  test: /\.(png|svg|jpg|gif)$/,
  use: [
    'file-loader'
  ]
},
{
  test: /\.(woff|woff2|eot|ttf|otf)$/,
  use: [
    'file-loader'
  ]
}
Copy the code

Of course, you can simplify the configuration information by combining the two Test re’s in one place.

Next we configure vue-loader.

(3) the vue – loader

To use the Vue single-file component, we need to process the.vue file using vue-loader.

Install vue-loader, CSS-loader, vue-style-loader, and vue-template-compiler first, the latter is also necessary, less will report errors.

Command:

npm i vue-loader css-loader vue-style-loader vue-template-compiler -D
Copy the code

Then we configure webpack.base.conf.js by adding the following code to the module.rules property of the file:

{
  test: /\.vue$/,
  loader: 'vue-loader'
},
{
  test: /\.css$/,
  use: ['vue-style-loader', 'css-loader']
}
Copy the code

This configuration is not enough. According to vue-loader’s official website, we need to configure a plug-in and then configure the resolve. Alias alias, otherwise Webpack will not be able to find the Vue module.

To configure the plug-in, first introduce the following in the file header:

const VueLoaderPlugin = require('vue-loader/lib/plugin');
Copy the code

Then add the plugin object to the plugins array:

new VueLoaderPlugin(),
Copy the code

We then configure the alias as well, setting resolve.alias to the following object:

{ 'vue$': 'vue/dist/vue.esm.js', '@': path.resolve(__dirname, '.. /src'), }Copy the code

This makes it easy for Webpack to find Vue, and when we introduce dependencies in JavaScript files, we can easily use @ instead of SRC, saving the trouble of writing file paths.

We’ll also add a resolve.extensions attribute so we can omit the suffix when importing dependencies or files:

extensions: ['*', '.js', '.json', '.vue'],
Copy the code

The Extensions property is an array. After this configuration, we import JavaScript files, JSON files, and Vue single-file components in JavaScript files without suffixes.

The above steps are very important, best not to omit.

Next, let’s verify that the Vue single-file component is available.

Install the Vue:

npm i vue --save
Copy the code

Then modify the contents of the index.js file as follows:

import Vue from 'vue';
import App from './App';

new Vue({
  el: '#app',
  template: '<App/>',
  components: { App }
});
Copy the code

Then create an app. vue file in the same directory with the following contents:

<template> <h1>Hello World! </h1> </template> <script> export default { name: 'App' } </script> <style> html, body { padding: 0; margin: 0; box-sizing: border-box; font-size: 16px; } </style>Copy the code

Run the command NPM run dev to see a large first-level title — Hello World!

At this point, our project is ready to be developed using the Vue single-file component, but we’re not done yet, and we have some work to do.

Optimize CSS code

Here we use the Autoprefixer plugin for PostCSS to automatically prefix our CSS code for different browsers.

First install dependencies:

npm i postcss-loader autoprefixer -D
Copy the code

Then modify the CSS configuration item in module.rules as follows:

{
  test: /\.css$/,
  use: ['vue-style-loader', 'css-loader', 'postcss-loader']
}
Copy the code

Then add the configuration file postcss.config.js to the root directory of our project, and the content is as follows:

module.exports = {
  plugins: [
    require('autoprefixer')
  ]
}
Copy the code

This means we are going to use the Autoprefixer plug-in.

After that, we can have fun writing code and verify for ourselves that the prefix is automatically added, which I won’t go into here.

6. Enable hot update

Webpack 4 is relatively easy to enable hot updates. The steps are as follows:

Modify webpack.dev.conf.js to set hot to true in the devServer property, which means hot updates are enabled. But that’s not enough, we need to add a plug-in and continue to modify webpack.dev.conf.js.

Set its plugins properties as follows:

const webpack = require('webpack'); / / in the file header introduced webpack rely on [new webpack. HotModuleReplacementPlugin ()]Copy the code

This enabled CSS hot updates (because vUE style-loader encapsulates style-loader, hot updates are available out of the box), but JavaScript hot updates are not yet available, and we refresh the browser every time we change code, so we need to continue to configure.

To make JavaScript modules HMR, we need to add the following code at the bottom of our entry file (index.js) :

if (module.hot) {
  module.hot.accept();
}
Copy the code

Now we can do HMR.

Vii. Package the third-party library separately

Every time we package a project, we package the referenced third-party dependencies, such as Vue, VUe-Router, React, etc. However, the code of these libraries is basically unchanged, so we don’t need to build each package, so we’d better extract these third-party libraries and package them separately to reduce the packaging time.

The official plug-in is DllPlugin, but the configuration of this plug-in is cumbersome. Someone on the Internet recommended a better plug-in – autoDLL-webpack-plugin, is really very useful.

Here is how it is configured:

First install:

npm i autodll-webpack-plugin -D
Copy the code

Then in webpack.base.conf.js we introduce:

const AutoDllPlugin = require('autodll-webpack-plugin');
Copy the code

Then add this plug-in to the plugins property:

new AutoDllPlugin({
  inject: true, // will inject the DLL bundle to index.html
  debug: true,
  filename: '[name]_[hash].js',
  path: './dll',
  entry: {
    vendor: ['vue', 'vue-router', 'vuex']
  }
})
Copy the code

Inject true, the plugin automatically inserts the packaged third-party library files into HTML. Filename is the name of the packaged file. Path is the packaged path. The entry is the entry, vendor is the name you specify, and the array content is the name of the third-party library to package. Don’t write the full path, Webpack will automatically find it in node_modules.

Each time a package is packaged, the plug-in checks to see if any third-party libraries registered with Entry have changed. If not, the plug-in uses the package file in the cache, reducing the packaging time, and the Hash does not change.

8. Extract common code:

Use the splitChucksPlugin plug-in, which comes with Webpack without installing third-party dependencies.

Usage:

Add the following plug-in object to the plugins property of webpack.base.conf.js;

new webpack.optimize.SplitChunksPlugin()
Copy the code

This means that you will use the default extract configuration to extract your common code. If you do not want to use the default configuration, pass the configuration object to the plug-in constructor.

For specific configuration, please refer to the webPack4 – SplitChunksPlugin user guide, which is very clear and detailed about the function of the configuration item.

Use the Stylus preprocessor

I personally like stylus because it’s more freeform to write, like Python, with fewer rules and less complex to use.

Introduction method:

First download the Stylus and stylus-Loader dependencies:

npm i stylus stylus-loader -D
Copy the code

Then add a configuration object to handle the stylus file in the configuration item module.rules.

The configuration information is as follows:

{
  test: /\.styl(us)$/,
  use: ['vue-style-loader', 'css-loader', 'stylus-loader', 'postcss-loader']
}
Copy the code

You can then use stylus to write CSS simply by adding lang=’stylus’ to the style tag of the Vue single-file component.

Extract CSS to a single file

The configuration method of this function is explained clearly on the Vue Loader official website.

Using the mini-CSs-extract-plugin, first install:

npm i mini-css-extract-plugin -D
Copy the code

Then introduce the following in the header of the configuration file:

const MiniCssExtractPlugin = require('mini-css-extract-plugin')
Copy the code

Then when you want to extract the CSS (production, packaging, for example), you will have all the vue – style – in the original configuration file loader is replaced by MiniCssExtractPlugin. Loader, Do not touch any other CSS-loader, stylus-loader, etc.

Finally, modify the plugins option and insert the following plug-in:

new MiniCssExtractPlugin({
  filename: "[name].css",
  chunkFilename: "[id].css"
})
Copy the code

Once packaged, you’ll find that all your CSS code has been extracted into a single CSS file.

harvest

  • Be careful with the configuration. An error may result in an unexpected error.
  • Learn Webpack to practice, light theory to learn more abstract.
  • Check Webpack documents, in fact, a lot of questions are explained clearly, do not rush to the Internet to find answers.
  • Off-the-shelf scaffolding is the best example, such as vue-CLI, create-react-app. Take a look at how they are configured and learn a few things.

Example code in my GitHub repository, students need to take their own.

If there are any mistakes, please point out!