preface

When developing projects like the official website, the framework is generally not used. 1) The framework is large and there is little business logic for such projects like the official website, which is basically static page. 2) It is not conducive to SEO, so we have to build it from the beginning with Webpack. So here are some configuration and optimizations for webpack4.

GitHub full project address

1. Multi-entry and automatic HTML generation

entry: {
	index: "./src/js/index.js"./ / home page
	about: "./src/js/about.js".// About us
},
plugins: [
  // Automatically empty the dist directory
  new CleanWebpackPlugin(),
  // Set the HTML template generation path
  new HtmlWebpackPlugin({
  	filename: 'index.html'.template: './src/views/index.html'.chunks: ['index']}),new HtmlWebpackPlugin({
  	filename: 'about.html'.template: './src/views/about.html'.chunks: ['about']})],// Compile the output configuration
output: {
	Dist /js, [name] preserves the original JS file name
	filename: 'js/[name.[hash].js'.// Output path is dist
	path: path.resolve(__dirname, 'dist')}Copy the code

** Note: When packaging the production environment, you need to add the publicPath attribute to output, otherwise it will not be resolved to the resource directory **

output:{ ... .publicPath: '/'
}
Copy the code

When there are too many pages, you can use the method of dynamic loading file to import:

const fs = require("fs");
let htmlPlugins = [];
const files = fs.readdirSync(path.resolve(__dirname, ".. /src/views"));
htmlPlugins = files.map((item) = > {
    return new HtmlWebpackPlugin({
        filename: item,
        template: `./src/views/${item}`.chunks: [item.split(".") [0]],}); });module.exports = { ...... . htmlPlugins, }Copy the code

Entry can be done the same way.

2. Hot update

npm install webpack-dev-server --save-dev
Copy the code

Add configuration:

devServer: {
	contentBase: "./dist".port: 8888.hot: true,},Copy the code

3. The compiler es6

npm install babel-loader @babel/core @babel/preset-env --save-dev
npm install @babel/plugin-transform-runtime @babel/plugin-transform-modules-commonjs --save-dev
npm install @babel/runtime --save
Copy the code

The configuration is as follows:

{
  test: /\.js$/,
  exclude: /(node_modules|bower_components)/,
  use: {
  loader: "babel-loader".options: {
    presets: ["@babel/preset-env"].plugins: ["@babel/plugin-transform-runtime"."@babel/plugin- transform-modules-commonjs"],}}},Copy the code

Load the CSS and SCSS

Installation-dependent dependencies

npm install style-loader css-loader --save-dev
npm install sass-loader node-sass --save-dev
Copy the code

Extract CSS into separate files

npm install mini-css-extract-plugin --save-dev
Copy the code

Add configuration:

rules: [
  {
  	test: /\.css$/,
  	use: [MiniCssExtractPlugin.loader, "css-loader"],}, {test: /\.scss$/,
  	use: [MiniCssExtractPlugin.loader, "css-loader"."sass-loader"]}]Copy the code

5. Pack images in the CSS

Install the url – loader

npm install url-loader --save-dev
Copy the code

Add configuration:

rules: [
	...,
  {
    test: /\.(png|svg|jpg|gif|webp)$/,
    use: [
      {
        loader: "url-loader".options: {
          // Actual path of image output (relative to dist)
          outputPath: "images".// Convert to base64 when the value is smaller than a certain KB
          limit: 0.name: "[name].[ext]".esModule: false.// Higher versions of url-loader require this attribute},},],},Copy the code

6. Load images in HTML

Install dependencies:

npm install html-loader --save-dev
Copy the code

Add configuration:

rules:[
...,
{
  test: /\.(html)$/,
  use: [
    {
      loader: "html-loader".options: { // The configuration item has changed after the revision. For details, see GitHub
        attributes: true.minimize: true,},},],},Copy the code

7. Handle third-party libraries. The following uses jQuery as an example

npm install jquery --save
Copy the code

Ready to use after introduction

import $ from 'jquery'
Copy the code

However, if multiple pages are used in a project and importing each page is cumbersome, you can use webPack’s global importing plug-in:

plugins: [
  ...,
  new webpack.ProvidePlugin({
    $: "jquery".jQuery: "jquery",}),]Copy the code

You can then use jquery directly on all pages instead of introducing it separately.

8. Code reuse

When developing multi-page applications, there are often situations where code needs to be used in multiple places, such as the head and bottom of the official website, and copy-paste is too low, so we need to implement code reuse. Here is the use of htMl-withimg-loader this loader, this loader can replace HTML-loader to solve the problem of loading images in HTML, and support code reuse. Install dependencies:

npm install html-withimg-loader --save-dev
Copy the code

Add configuration:

module: {// Delete html-loader configurations
	rules:[
		{
			test: /\.(html)$/i,
			loader: "html-withimg-loader".// Fix img tag path not found in HTML}}]Copy the code

The syntax for reuse is as follows:

<div>
    #include("./layout/top.html")
    <! -- The child page will be introduced, and the img tag in the child page will also be processed -->
</div>
Copy the code

Then you can reuse code in pages such as index.html

<div>#include(".. /component/header.html")</div>
Copy the code

Header. CSS and header.js must be added to the js file on the page, for example, index.js

import "./header.js";
import ".. /css/header.scss";
Copy the code

Note that htML-withimg-loader cannot package audio and video files. Therefore, multimedia files in HTML need to be imported into the corresponding JS file, such as index.js

import ".. /images/home/video1.mp4"; // Process video files
Copy the code

9. Package optimization

9.1 Use the BundleAnalyzerPlugin to package the result visualization plug-in

Install dependencies:

npm install webpack-bundle-analyzer --save-dev
Copy the code

Add configuration:

plugins:[
	...,
	new BundleAnalyzerPlugin({
  	analyzerPort: 8889,})]Copy the code

9.2 Splitting a Module

Because multiple pages will use third-party packages such as jquery, each file will be packed with jquery, resulting in too much volume, because you can use splitChunks to split modules and pack them only once:

optimization: {
  splitChunks: {
    cacheGroups: {
      vendor: {
        name: "vendor".test: /[\\/]node_modules[\\/]/,
        chunks: "all".priority: 10./ / priority}},}},Copy the code