preface

This is the third note in my study of Webpack, the road above

  • Webpack Study Notes (1) : First meeting, please give advice
  • Webpack Study Notes (2) : Basic properties management

In this blog post, I want to show you how to configure the environment for a WebPack project. When it comes to environment configuration, it’s natural to think of the config.webpack.js file mentioned earlier. Yes, this file is used to configure the WebPack environment. However, in actual engineering applications, the development environment and production environment need to be configured separately to achieve the purpose of engineering optimization. In this blog, I will focus on three topics: development environment, production environment, and environment variables. Once you’ve learned these things, you’re almost ready to build a simple WebPack engineering template.

Development vs. production environment

The first two notes just get WebPack up and running, but they fall far short of the actual development needs. In engineering practice, it is necessary to separate development environment and production environment. In actual development, you need to:

  1. Provide HTTP services instead of opening HTML files locally to see the effects;
  2. It’s also better to preview in real time, rather than repackage every time you change the contents of a file;
  3. Convenient debugging in the development, accurately locate the error of the source file.

Different from the development environment, in the production environment, we focus more on compressed bundles, lighter source maps, resource optimization, etc. Therefore, we need to separate the development and production environments.

The development environment

Building a WebPack development environment is divided into the following three steps:

  1. willmodeSet todevelopment

Just set the mode property in the config.webpack.js file:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
 module.exports = {
   mode: 'development'.// Newly added
   entry: {
     index: './src/index.js'.print: './src/print.js',},devtool: 'inline-source-map'.plugins: [
     new HtmlWebpackPlugin({
       title: 'Development',})],output: {
     filename: '[name].bundle.js'.path: path.resolve(__dirname, 'dist'),
     clean: true,}};Copy the code
  1. Use source Map to track errors in source files

When using WebPack to package source code, errors encountered during the execution of the program are directly located in the packaged bundle file, and it is difficult to trace the errors in the source code. This brings great inconvenience to the debugging of the code. To solve this debugging difficulty, JavaScript provides the source Map feature, which maps compiled code back to source code. This makes it easy to track errors and warnings encountered during the execution of the program. To use source map, simply declare the devTool property in the config.webpack.js file:

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

module.exports = {
    mode: 'development'.entry: {
        index: './src/index.js'.print: './src/print.js',},devtool: 'inline-source-map'.// Newly added
        plugins: [
           new HtmlWebpackPlugin({
           title: 'Development',})],output: {
         filename: '[name].bundle.js'.path: path.resolve(__dirname, 'dist'),
         clean: true,}};Copy the code

In the code here, the inline-source-map option is used. In addition, there are other source-map options as shown in the table below:

Devtool options Configure the results
source-map Produces a complete and fully functional file within a separate file. This file has the bestsource mapBut he will slow down the packing
cheap-module-source-map Generate one without column mapping in a separate filemap, without column mapping improves packaging speed, but also makes the browser developer tool correspond to specific rows, not specific columns (symbols), which can be a debugging inconvenience
eval-source-map useevalPackage the source file module to produce a clean and complete one in the same filesource map, but the execution of the output JS file after packaging has performance and security risks. This is a great option in development, but you must not enable it in production
cheap-module-eval-source-map This is the fastest generation when packaging filessource mapMethod, generated bysource mapWill be displayed as the packaged JavaScript file, without column mapping, andeval-source-mapOptions have similar disadvantages

Among them, eval-source-map is a good option for small to medium-sized projects, but it should only be used during the development phase; The cheap-modol-eval-source-map method is faster to build, but is not good for debugging, and is recommended for large projects where time costs are considered.

  1. Choose a development tool

Webpack provides three tools for easy debugging in development:

  • Webpack’s Watch Mode: If the file is updated, the code will be recompiled without manual creation
  • Webpack-dev-server: Provides a basic Web server
  • Webpack-dev-middleware: This allows you to send WebPack-processed files to a server, which you need to create manually

Watch Mode

This tool does not require additional plugins, just tell webpack “watch” to start Watch Mode. If you run it using the NPM script command, you need to add the command to the package.json file.

  • package.json:
 {
   "name": "webpack-demo"."version": "1.0.0"."description": ""."private": true."scripts": {
     "test": "echo \"Error: no test specified\" && exit 1"."watch": "webpack --watch".// Newly added
     "build": "webpack"
   },
   "keywords": []."author": ""."license": "ISC"."devDependencies": {
     "html-webpack-plugin": "^ 4.5.0." "."webpack": "^ 5.4.0"."webpack-cli": "^ 4.2.0"
   },
   "dependencies": {
     "lodash": "^ 4.17.20"}}Copy the code

After the configuration is complete, run the following command.

npm run watch

webpack-dev-server

  1. Install the webpack-dev-server plug-in

npm install –save-dev webpack-dev-server

  1. Configuration wepack. Config. Js
 const path = require('path');
 const HtmlWebpackPlugin = require('html-webpack-plugin');

 module.exports = {
   mode: 'development'.entry: {
     index: './src/index.js'.print: './src/print.js',},devtool: 'inline-source-map'.devServer: {                           // Newly added
    contentBase: './dist'.// Newly added
  },                                     // Newly added
   plugins: [
     new HtmlWebpackPlugin({
       title: 'Development',})],output: {
     filename: '[name].bundle.js'.path: path.resolve(__dirname, 'dist'),
     clean: true,}};Copy the code
  1. Add script that runs dev Server directly
"scripts": {
     "test": "echo \"Error: no test specified\" && exit 1"."watch": "webpack --watch"."start": "webpack serve --open".// Newly added
     "build": "webpack"
   },
Copy the code

webpack-dev-middleware

  1. Install Webpack-dev-Middleware and Express (select where you want to install them, or in devDependencies if you need them only for development; Install in Dependencies if you also need it in production.)

NPM install –save-dev webpack-dev-middleware NPM install –save Express or NPM install –save-dev Express

  1. Adjust the webpack.config.js file
const path = require('path');
 const HtmlWebpackPlugin = require('html-webpack-plugin');

 module.exports = {
   mode: 'development'.entry: {
     index: './src/index.js'.print: './src/print.js',},devtool: 'inline-source-map'.devServer: {
     contentBase: './dist',},plugins: [
     new HtmlWebpackPlugin({
       title: 'Development',})],output: {
     filename: '[name].bundle.js'.path: path.resolve(__dirname, 'dist'),
     clean: true.publicPath: '/'.// Newly added}};Copy the code
  1. Add server.js to the project directory
Webpack - demo | - package. Json | - webpack. Config. Js | - server. Js / / new add | - / dist | - / SRC | - index. Js | - print. Js |  - /node_modulesCopy the code
  1. Write the contents of the server.js file
const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');

const app = express();
const config = require('./webpack.config.js');
const compiler = webpack(config);

// Tell Express to use webpack-dev-middleware,
// And the webpack.config.js configuration file as the base configuration.
app.use(
  webpackDevMiddleware(compiler, {
    publicPath: config.output.publicPath,
  })
);

// Serve the file to port 3000.
app.listen(3000.function () {
  console.log('Example app listening on port 3000! \n');
});
Copy the code
  1. Add script that runs server directly

Add the corresponding command to the package.json file scripts:

 "scripts": {
     "test": "echo \"Error: no test specified\" && exit 1"."watch": "webpack --watch"."start": "webpack serve --open"."server": "node server.js".// Newly added
     "build": "webpack"
   },
Copy the code

The production environment

The first thing you need to do in this section is to separate the production environment from the development environment by splitting webpack.config.js into two files: webpack.dev.js and webpack.prod.js. These two files configure the development and production environments, respectively. The file directory after the separation is as follows:

webpack-demo
| - package.json
| - webpack.dev.js
| - webpack.prod.js
| - /dist
| - /src
    | - index.js
| - /node_modules
Copy the code

The next step is to write the configuration in these two files:

  • webpack.dev.js
 const path = require('path');
 const HtmlWebpackPlugin = require('html-webpack-plugin');

 module.exports = {
   mode: 'development'.devtool: 'inline-source-map'.devServer: {
     contentBase: './dist',},entry: {
     app: './src/index.js',},plugins: [
     new HtmlWebpackPlugin({
       title: 'Production',})],output: {
     filename: '[name].bundle.js'.path: path.resolve(__dirname, 'dist'),
     clean: true,}};Copy the code
  • webpack.prod.js
 const path = require('path');
 const HtmlWebpackPlugin = require('html-webpack-plugin');

 module.exports = {
   mode: 'production'.entry: {
     app: './src/index.js',},plugins: [
     new HtmlWebpackPlugin({
       title: 'Production',})],output: {
     filename: '[name].bundle.js'.path: path.resolve(__dirname, 'dist'),
     clean: true,}};Copy the code

Finally, point scripts to the new command:

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

It is easy to see that there are many similarities between the two files. To avoid duplication, consider putting the same parts of both files in the same file, webpack.mon.js, and just different configurations in webpack.dev.js and webpack.prod.js. The directory structure becomes:

webpack-demo
| - package.json
| - webpack.common.js
| - webpack.dev.js
| - webpack.prod.js
| - /dist
| - /src
    |- index.js
| - /node_modules
Copy the code

After changing the file directory, you should also install a plug-in that combines the configurations of the two files:

npm install –save-dev webpack-merge

The code of the three files is as follows:

  • webpack.common.js
 const path = require('path');
 const HtmlWebpackPlugin = require('html-webpack-plugin');

 module.exports = {
   entry: {
     app: './src/index.js',},plugins: [
     new HtmlWebpackPlugin({
       title: 'Production',})],output: {
     filename: '[name].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

The environment variable

The webpack command line environment configuration –env argument allows any number of environment variables to be passed in. As for access to environment variables, you can access them in webpack.config.js. It can also be obtained from the Node environment:

process.env.NAME
Copy the code