[webpack series] Basics

Time:2021-12-9

Webpack Basics

Basic concepts

WebpackIs a modernJavaScriptStatic module packer for the application. WhenwebpackWhen processing an application, it recursively builds a dependency graph containing each module required by the application, and then packages all these modules into one or morebundle

Four core concepts

  1. Entry: BuildingWebpackEntry module of internal dependency graph
  2. Output: outputWebpackPackedBundles
  3. Loader: loader,WebpackNative can only resolveJavaScriptDocuments,LoaderGive WaywebpackHas the ability to load and parse nonJavaScriptAbility to document.
  4. Plugins: ExtensionsWebpackFeatures that allowWebpackMore flexibility. stayWebpackMany events will be broadcast in the life cycle of operation,PluginYou can monitor these events and pass them at the right timeWebpackProvidedAPIChange the output.

Webpack basic configuration

Initialize project

Create a new folderwebpack-demo, use in this directorynpm init -yPerform project initialization.

mkdir webpack-demo && cd webpack-demo
npm init -y

Run the following command to install the latest or specific version

npm i -D webpack
npm i -D [email protected]<version>

If you usewebpack 4+Version, you also need to installCLI

npm i -D webpack-cli
  • npm i -Dbynpm install --save-devInstall an installation package for the development environment
  • npm i -Sbynpm install --saveAn installation package to be packaged into a production environment

Now installedwebpackThe version number is:

├── [email protected]
└── [email protected]

newly buildsrc/index.jsFile:

// src/index.js

class HelloComponent {
  constructor (content = '') {
    this.content = content;
    this.render();
  }
  render () {
    const element = document.createElement('div');
    element.innerHTML = this.content;
    document.body.appendChild(element);
  }
}

new HelloComponent('hello webpack');

It can now be executed directlynpx webpack, default isproductionpattern.
You can alsopackage.jsonMediumscriptsConfigure one in thebuildCommand, mode specified asproduction
webpackBy default, the./src/index.jsAs an entry file, it is packaged to by defaultdist/main.js

// ...
"scripts": {
  "build": "webpack --mode=production"
}
// ...

adoptnpm run buildWe can execute the commands we define, which is much moredist/main.jsFile, this is the packagejscode.

Webpack profile

Used in the above example iswebpackFor the default configuration, let’s define richer custom configurations.

New under root directorywebpack.config.jsfile

const path = require('path');

module.exports = {
  Mode: 'development', // mode
  Entry: path. Resolve (_dirname, 'Src / index. JS'), // entry file
  output: {
    Path: path. Resolve (_dirname, 'dist'), // output directory
    Filename: 'bundle. JS' // output file name
  }
}

Change ourbuildCommands, specifyingwebpackPackage the files according to our configuration file

"scripts": {
  "build": "webpack --config webpack.config.js"
}

implementnpm run buildAs you can see,distNew in the directorybundle.jsFile. alsobundle.jsIt is packaged in development mode. You can see more information.

HTML webpack plugin

Now we have a packed onejsFile, need to addhtmlFile to introduce thisjsFile in the browser to see the effect.

In actual development, in order to avoid modifying the packagedjsThe file is cached by the browser and we can’t see the latest code. We will addhash, equivalent to the version number of this file. In this way, it is packaged after each modificationjsThe file names will be different. If you modify them manuallyhtmlMediumjsThe file name is too troublesome. We can use ithtml-webpack-pluginPlug-ins to automate these things.

installhtml-webpack-plugin

npm i -D html-webpack-plugin

newly buildpublic/index.htmlFile, modify ourwebpack.config.js

// webpack.config.js
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  //...
  plugins: [
    new HtmlWebpackPlugin({
      Template: path. Resolve (_dirname, 'public / index. HTML'), // specify the template file. If not specified, the default index.html file will be generated
      Filename: 'index. HTML' // packed file name
    })
  ]
}

implementnpm run buildCan seedistNew in the directoryindex.htmlFile, and automatically pack itbundle.jsDocument adoptionscriptTags are introduced.

Webpack dev server development tool

It can now be opened directly through the browserdist/index.htmlYes, but we need to change the code manually every timenpm run buildWait a minute. It’s too troublesome.

We can usewebpack-dev-serverTo solve this problem.webpack-dev-serverWill provide a simplewebServer and can be reloaded in real time.

installwebpack-dev-server

npm i -D webpack-dev-server

Modify the package.json file

// package.json
"scripts": {
  "dev": "webpack-dev-server --config webpack.config.js",
  "build": "webpack --config webpack.config.js"
}

npm run devAfter that, by defaultlocalhost:8080Create a service under. You can access it by accessing this addressdistFiles in the directory.

Can be inwebpack.config.jsyesdevServerConfigure

// webpack.config.js

module.exports = {
  // ...
  devServer: {
    contentBase: path.join(__dirname, 'dist'),
    Port: '9000', // specify the port. The default is 8080
    Compress: true // whether gzip compression is enabled
  }
  //...
}

aboutwebpack-dev-serverMore configurations are availableClick to view

mode

We arepackage.jsonTwo commands are defined, butmodeAll fordevelopment。 We can setprocess.env.NODE_ENVTo distinguish between development and production environments.

We need to install itcross-envTo implement cross platform settingsNODE_ENV

npm i -D cross-env
// package.json
"scripts": {
  "dev": "cross-env NODE_ENV=development webpack-dev-server --config webpack.config.js",
  "build": "cross-env NODE_ENV=production webpack --config webpack.config.js"
}

modifywebpack.config.js

// webpack.config.js

const isProduction = process.env.NODE_ENV == 'production';

module.exports = {
  mode: isProduction ? ' Production ':'development', // mode
  // ...
}

set upmodeDifferent values of can enable in the corresponding modewebpackBuilt in optimization

option describe
development Willprocess.env.NODE_ENVThe value of is set todevelopment。 EnableNamedChunksPluginandNamedModulesPlugin
production Willprocess.env.NODE_ENVThe value of is set toproduction。 EnableFlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPluginandUglifyJsPlugin.

Backward compatible JS syntax with Babel

Now our code has been packaged, but it has not been escaped to lower version code. We need to passBabelLai JiangECMAScript 2015+Version of the code is converted to backward compatibleJavaScriptSyntax so that it can run in current and old versions of browsers or other environments.

installbabel-loader

npm i -D babel-loader

In addition, we need to install the following dependencies

npm i -D @babel/core @babel/preset-env @babel/plugin-transform-runtime
npm i -S @babel/runtime @babel/runtime-corejs3

staywebpack.config.jsto configurebabel-loader

// webpack.config.js 
module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        use: ['babel-loader'],
        exclude: /node_ Modules // exclude node_ Modules directory
      }
    ]
  }
  // ...
}

Suggest toloaderappointincludeorexclude, excluding some directories that do not need to be compiled can improve the compilation efficiency, such asnode_modulescatalogue

There are two ways to configurebabel

  1. adopt.babelrcFile configuration

Create a new one under the root directory.babelrcFile, configured as follows:

// .babelrc

{
  "presets": ["@babel/preset-env"],
  "plugins": [
    [
      "@babel/plugin-transform-runtime",
      {
        "corejs": 3
      }
    ]
  ]
}
  1. staywebpackMedium configurationbabel
// webpack.config.js

module.exports = {
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ["@babel/preset-env"],
            plugins: [
              [
                "@babel/plugin-transform-runtime",
                {
                  "corejs": 3
                }
              ]
            ]
          }
        },
        exclude: /node_modules/
      }
    ]
  }
}

By executionnpm run dev, let’s seehttp://localhost:9000/bundle.jsIt is found that it is the low version code after escape.

Using source map

WhenwebpackWhen packaging source code, it is difficult to trace the original location of errors and warnings in the source code. To make it easier to track errors and warnings,JavaScriptProvidedsource mapFunction to map the compiled code back to the original source code.

In the development environment, you can setdevtoolValue isinline-source-map, the production environment is set tononeperhapssource-map

// webpack.config.js
const isProduction = process.env.NODE_ENV == 'production';

module.exports = {
  // ...
  devtool: isProduction ? 'source-map' : 'inline-source-map',
}

usesource-mapIt will eventually be packaged separately.mapAccording to the error information andmapLocate the file to the source code.

However, it is generally not directly.mapFile deployment toCDN, but will.mapThe file is sent to the error monitoring system so that we can analyze the source location of the error.

Processing style files

webpackCan only handlejsFile, if you want to processcssNeed helploader

If it is.css, what we needloaderyes:style-loadercss-loader, considering the compatibility problem, it is also necessary topostcss-loaderautoprefixer

If it is.less, still needless-loaderless

If it is.sassIf so, you needsass-loadernode-sass

Install corresponding dependencies

npm i -D style-loader css-loader postcss-loader autoprefixer less-loader less sass-loader node-sass

webpack.config.jsadd tocsslesssass loader

// webpack.config.js

module.exports = {
  // ..
  module: {
    rules: [
      // ...
      {
        test: /\.(c|le)ss$/,
        use: ['style-loader', 'css-loader', 'postcss-loader', 'less-loader'],
        exclude: /node_ Modules // exclude node_ Modules directory
      },
      {
        test: /\.sass$/,
        use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader'],
        exclude: /node_ Modules // exclude node_ Modules directory
      }
    ]
  }
}

New root directorypostcss.config.js

// postcss.config.js
module.exports = {
  plugins: [
    //Compatible browsers, adding prefixes
    require('autoprefixer')({
      overrideBrowserslist: [
        "Android 4.1",
        "iOS 7.1",
        "Chrome > 31",
        "ff > 31",
        "ie >= 8"
        //'last 10 versions', // used by the latest 10 versions of all mainstream browsers
      ],
      grid: true
    })
  ]
}

After the configuration is completed, create several new files to test

/* src/index.css */
div {
  width: 200px;
  height: 100px;
  display: flex;
}
// src/index.less
@color: yellow;
body {
  background: @color;
  display: flex;
}
// src/index.sass
$text-color: orange;
div 
  color: $text-color;
  display: flex;

Then three files are introduced into the entry file

// src/index.css
import './index.css';
import './index.less';
import './index.sass';

We can see that the style takes effect andflexThe browser prefix is also automatically added.

[webpack series] Basics

It should be noted thatloaderThe execution order of is from right to left. The execution order is:

less-loader/sass-loader => postcss-loader => css-loader => style-loader

  1. less-loaderProcess compilation.lessFile, convert it tocss
  2. sass-loaderProcess compilation.sassFile, convert it tocss
  3. postcss-loaderandautoprefixer, automatically generate browser compatibility prefix
  4. css-loaderhandlecssMedium@importurl(...)Equal statement
  5. style-loaderDynamic creationstyleLabel, willcssInsert intoheadin

Process media files such as pictures and fonts

We can useurl-loaderperhapsfile-loaderTo process local resource files.

file-loaderAfter some processing (mainly processing the file name and path and parsing the file)url), move the file to the output directory, andrequireThe location of the file returns the absolute path of the file.

url-loaderGeneral andfile-loaderUse together, function andfile-loaderSimilarly, if the file size is less than the limit, it will be returnedbase64code.

It needs to be installed at the same timefile-loaderandurl-loader

npm i -D file-loader url-loader 

to configurewebpack.config.js

// webpack.config.js

module.exports = {
  // ..
  module: {
    rules: [
      // ...
      {
        test: /\.(jpe?g|png|gif|webp|svg|eot|ttf|woff|woff2)$/i,
        use: [
          {
            loader: 'url-loader',
            options: {
              Limit: 10240, // when the 10K resource size is less than 10k, convert the resource to Base64. If it exceeds 10K, copy the image to the dist directory
              name: '[name]_ [hash: 6]. [ext] ', // set the file name. By default, the file name of the generated file is the MD5 hash value of the file content, and the original extension of the referenced resource will be retained
              Outputpath: 'assets', // output directory
              Esmodule: false // indicates whether to use the export of ES6 module. It is enabled by default
            }
          }
        ],
        exclude: /node_modules/
      }
    ]
  }
}

We modifysrc/index.sassfile

// src/index.sass
$text-color: orange;
div 
  color: $text-color;
  display: flex;
  background: url('../images/author.jpg');

After modifying the configuration file, we re NPM run dev to see that the image address has been replaced
[webpack series] Basics
npm run buildCan seedist/assetsThere’s this file

[webpack series] Basics

Note that if necessary at this timehtmlThe reference to this picture in the file needs to be written like this

<body>
  <img>
</body>

The path after final packaging is

[webpack series] Basics

Empty dist directory before packaging

After we modify the file package, the generatedhashValue and beforedistDifferent in will lead todistThere are more and more files under the, so we need to empty them before packingdistcatalogue

installclean-webpack-plugin

npm i -D clean-webpack-plugin
// webpack.config.js
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
  //...
  plugins: [
    // ...
    new CleanWebpackPlugin() 
  ]
}

This will be automatically cleared before each packagedistFiles in the directory.

last

Through the above practice, wewebpackHave a preliminary understanding of the basic configuration of. All the code in this article canView GitHub

The follow-up will continue to be launchedwebpackOther contents of the series~

If you like this article, please praise it~

[webpack series] Basics

More interesting content, welcome to WeChat official account.