preface

Webpack, as the most popular packaging tool, is a big front-end tool. The mainstream development framework Vue/React also integrates WebPack in their official scaffolding vuE-cli /react-create-app. Although using scaffolding can quickly achieve project development, But the internal hidden configuration details, can not easily achieve personalized configuration, and learning Webpack is also very necessary.

The front page of its official website vividly illustrates what Webpack is, as follows:

To make it easier to read and learn about Webpack from the beginning, I’ve broken this series into several articles

  • Implement a React project webpack configuration from 0 to 1.this)
  • Best Practices for WebPack Performance Optimization (Core Concepts)
  • Implement a simplified version of WebPack (Implementation principle)

Development needs

React supports automatic code refresh, automatic javascript code compatibility, one-click compression, static resource handling, problem debugging, and less styling.

The core configuration

The entrance (entry)

Entry is the entry to the configuration module, which can be abstracted as input, and Webpack performs the first step of construction by searching and recursively resolving all the modules that the entry depends on. Entry configuration is mandatory. Otherwise, Webpack will exit with an error.

module.exports = {
  entry: './path/to/my/entry/file.js'};Copy the code

Output (output)

The Output attribute tells WebPack where to export the bundles it creates and how to name those files. The default value for the main output file is./dist/main.js, and the other generated files are placed in the./dist folder by default.

output: {
  path: path.resolve(__dirname, 'dist'), // The configuration output file is stored in the local directory. It must be an absolute path of type string
  filename: 'my-first-webpack.bundle.js'./ / file namePublicPath:'/'.// output.publicPath Configures the URL prefix published to online resources. The prefix is string. The default is an empty string ", that is, a relative path.
  clean: true.// Automatically clear the previous dist package
}
Copy the code

Loader

Loader can be regarded as a translator with file conversion function. The newly introduced Loader should be installed before re-executing Webpack construction. To know which properties Loader supports, we need to refer to the documents. This can be found on the CSS-Loader home page. Commonly used loader.

  • The value of the use attribute must be an array of Loader names in the order in which loaders are executedBy the first;
  • Each Loader can passURL querystringFor example, csS-loader? Minimize tells CSS-Loader to turn on CSS compression.
 module: {
    rules: [{// Use the re to match the CSS file to be converted with the loader
        test: /\.css$/,
        use: ['style-loader'.'css-loader? minimize']],}}Copy the code

plugin

Plugin is designed to extend Webpack functionality by injecting hook implementations into the build process, which gives Webpack a lot of flexibility. Plug-ins are used to solve other problems that cannot be implemented by loader. Plug-ins need to be installed. The plugin is commonly used.

Here is an example of the htmL-webpack-plugin that automatically generates HTML

plugins: [
  new HtmlWebpackPlugin({
    title: 'Set up a React project',}),]Copy the code

Basic installation

Create a directory, initialize NPM, install Webpack locally, download the required Loader and plugin.

  • Webpack-dev-server (provides HTTP services)
  • Html-webpack-plugin (automatic generation of DIST HTML)
  • Css-loader, style-loader (CSS support)
mkdir webpack-demo
cd webpack-demo
npm init -y
npm install webpack webpack-cli webpack-dev-server html-webpack-plugin --save-dev css-loader style-loader
Copy the code
Webpack - demo | - package. Json | - webpack. Config. Js + / SRC + | | - index. Js + | - index. CSS + | - a picture. PNGCopy the code

Index.js file to display text and introduce styles

import './index.css'
const div = document.createElement('div')

// Write text to add the class name
div.innerHTML = "hello, webpack";
div.classList.add('hello');

document.body.appendChild(div)
Copy the code

CSS content, using background images

.hello {
  width: 200px;
  height: 200px;
  color: red;
  background: url('./girl.jpg')}Copy the code

Configuration webpack. Config. Js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  mode: 'development'.// Development mode
  // JavaScript executes the entry file
  entry: {
    index: './src/index.js',},devtool: 'inline-source-map'.// Source Map is supported for easy debugging, this configuration is for example only, not for production environment
  plugins: [
    new HtmlWebpackPlugin({
      title: 'Webpack includes teaching but not meeting (1)',})],module: {
    rules: [{// Use the re to match the CSS file to be converted with the loader
        test: /\.css$/,
        use:['style-loader'.'css-loader'] {},test: /\.png|svg|jpg|jpeg|gif$/.// Support the use of images
        type: 'asset/resource'}},output: {
    // Merge all dependent modules into a bundle.js file
    filename: 'bundle.js'.// Put the output files in the dist directory
    path: path.resolve(__dirname, './dist'),
    clean: true.// Delete the dist file automatically before each update}};Copy the code

Package. json uses webpack-dev-server to start the local service

"scripts": {
    "start": "webpack serve --open".// open Automatically opens the page when it is started
  },
Copy the code

The console runs NPM run start to view the result

Error modifying index.js intentionally

import './index.css'
const div = document.createElement('div')
// Write text to add the class name
div.innerHTML = "hello, webpack";
div.classList.ad('hello'); // There is an error here

document.body.appendChild(div)

Copy the code

View console

Devtool: ‘inline-source-map’ takes effect

So far, we have implemented a WebPack project that supports providing HTTP services instead of using local file previews; Monitor the changes of files and automatically refresh the web page to achieve real-time preview; Support Source Map for easy debugging, support CSS and image import, more detailed steps can refer to webPack start.

Use the react

Install Babel

npm i babel-core babel-loader babel-preset-env babel-preset-react babel-preset-stage-0 less-loader -D

  • Babel-loader: indicates the Babel loader
  • Babel-preset -env: Only those features not yet supported are compiled based on the configured ENV.
  • Babel-preset -react: JSX is converted to JS
  • Less-loader Less converter

Add the. Babelrc configuration file

{
  "presets": ["env"."stage-0"."react"] // Parse from left to right
}
Copy the code

SRC added index.html as template file

<! DOCTYPEhtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Webpack includes teaching but not meeting (1)</title>
</head>
<body>
<div id="root"></div>
</body>
</html>
Copy the code

Index. Js write the react

import React, { Component } from 'react';
import { render } from 'react-dom'
import './index.less'

function Hello(params) {
  return <div className="hello">Hello, webpack</div>
}


render(<Hello />.document.getElementById('root'))

Copy the code

Modify the webpack. Config. Js

Add template files for HTML, use babel-loader for JS files, and use less-loader for less

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = (env) = > {
  // JavaScript executes the entry file
  return {
    mode: 'development'.entry: {
      index: './src/index.js',},// devtool: 'inline-source-map',
    devServer: {contentBase: "./dist".// The directory where the page is loaded by the local server
    },
    plugins: [
      new HtmlWebpackPlugin({
        title: 'Webpack includes teaching but not meeting (1)'.template: './src/index.html' // Add template entry}),].module: {
      rules: [{test:/\.js$/.// Match js using babel-loader
          use:{
              loader:'babel-loader'}}, {// Use the re to match the less file to be converted with the loader
          test: /\.css$/,
          use:['style-loader'.'css-loader'.'less-loader'] {},test: /\.png|svg|jpg|jpeg|gif$/,
          type: 'asset/resource'}},output: {
      // Merge all dependent modules into a bundle.js file
      filename: 'bundle.js'.// Put the output files in the dist directory
      path: path.resolve(__dirname, './dist'),
      clean: true,}}};Copy the code

Look at the effect

React is already available

Distinguish between development and production environments

There are huge differences in build goals between development and production environments.

  • In a development environment, we need: a powerful source map and a Localhost Server with live reloading or hot Module replacement capabilities
  • Production environment goals move to other areas, focusing on bundle compression, lighter source maps, resource optimizations, and so on to improve load times.

To follow logical separation, we generally recommend writing separate WebPack configurations for each environment.

To split webpack.config.js, use webpack-merge to merge config

npm install –save-dev webpack-merge

 webpack-demo
 + |- webpack.common.js
 + |- webpack.dev.js
 + |- webpack.prod.js
Copy the code

webpack.common.js

const path = require('path');
 const HtmlWebpackPlugin = require('html-webpack-plugin');

 module.exports = {
    entry: {
      index: './src/index.js',},plugins: [
      new HtmlWebpackPlugin({
        title: 'Webpack includes teaching but not meeting (1)'.template: './src/index.html'}),].module: {
      rules: [{test: /\.js$/,
          use: 'babel-loader'.exclude: /node_modules/.// Remove the node_modules conversion
        },
        {
          // Use the re to match the CSS file to be converted with the loader
          test: /\.less$/,
          use:['style-loader'.'css-loader'.'less-loader'].exclude: /node_modules/}, {test: /\.png|svg|jpg|jpeg|gif$/,
          type: 'asset/resource'}},],output: {
     filename: 'bundle.js'.path: path.resolve(__dirname, 'dist'),
     clean: true,}};Copy the code

webpack.dev.js

 const { merge } = require('webpack-merge');
 const common = require('./webpack.common.js');

 module.exports = merge(common, {
   mode: 'development'.devtool: 'inline-source-map'.devServer: {
     contentBase: './dist',}});Copy the code

webpack.prod.js

const { merge } = require('webpack-merge');
 const common = require('./webpack.common.js');

 module.exports = merge(common, {
   mode: 'production'});Copy the code

Modify startup commands to differentiate environments

"scripts": {
   "start": "webpack serve --open --config webpack.dev.js"."build": "webpack --config webpack.prod.js"
}
Copy the code

summary

This time we used WebPack to configure a basic React development project, and can distinguish between the development environment and the production environment configuration. There are many optimization points in this configuration, such as subcontracting, compression, preloading… Best practices for WebPack will be summarized in the next article.

Our goal in this article is to let you start from the simple, manual configuration of a basic project, novice words will encounter a lot of error, most of the package may be the problem, operate several times. The source address

The resources

Wepack Chinese document

Easy to understand Webpack