Webpack 4 series of tutorials (16): development mode and production mode.

Keywords: Javascript Webpack npm github JSON

Author Click This is the last tutorial in the webpack 4 series. This article builds on all the previous tutorials and does a real webpack project! I spent three months sorting out this tutorial, perfecting the relevant sample code and becoming more familiar with the theory and application of webpack. Of course, thank you for your support. Okay, I'm done with my feelings and I'm going to get to the point.

0. Course introduction and information

The code catalogue for this lesson is as follows:

1. How to separate development environment and production environment?

Friends who are familiar with scaffolding in Vuejs or ReactJs should know that there is a / build / folder in the root directory dedicated to the relevant code of the webpack configuration file.

Unlike demo in our previous 15 lessons (only one configuration file, webpack.config.js), in order to separate the development environment from the production environment, we need to write the corresponding webpack configuration code.

There is no doubt that some plug-ins and configurations are common to both environments, so they should be refined to avoid duplication of effort. For example, in the previous catalog screenshot, build/webpack.common.conf.js saves configuration files that are common to both environments. build/webpack.dev.conf.js and build/webpack.prod.conf.js are special configurations for development and production environments, respectively.

2. Write package.json

As mentioned in the previous section, scripts options need to be configured for better command invocation. Imitate the command format of vue-cli and write the following package.json:

{
  "scripts": {
    "dev": "webpack-dev-server --env development --open --config build/webpack.common.conf.js",
    "build": "webpack --env production --config build/webpack.common.conf.js"
  },
  "devDependencies": {
    "babel-core": "^6.26.3",
    "babel-loader": "^7.1.5",
    "babel-plugin-transform-runtime": "^6.23.0",
    "babel-preset-env": "^1.7.0",
    "clean-webpack-plugin": "^0.1.19",
    "css-loader": "^1.0.0",
    "extract-text-webpack-plugin": "^4.0.0-beta.0",
    "html-webpack-plugin": "^3.2.0",
    "jquery": "^3.3.1",
    "style-loader": "^0.21.0",
    "webpack": "^4.16.1",
    "webpack-cli": "^3.1.0",
    "webpack-dev-server": "^3.1.4",
    "webpack-merge": "^4.1.3"
  },
  "dependencies": {
    "babel-polyfill": "^6.26.0",
    "babel-runtime": "^6.26.0"
  }
}

Run according to configuration:

  • npm run dev: enter development debugging mode
  • npm run build: Generating packaged files

It can also be seen that build/webpack.common.conf.js is not only a common code for both environments, but also an entry file for webpack commands.

3. How to merge different configurations of webpack?

According to what I said earlier, we have three configuration files. So how to introduce the configuration of development or production environment in build/webpack.common.conf.js and incorporate it correctly?

At this point, we need to use webpack-merge as a third-party library. Here is an example code:

const merge = require("webpack-merge");

const productionConfig = require("./webpack.prod.conf");
const developmentConfig = require("./webpack.dev.conf");

const commonConfig = {}; // ... omission

module.exports = env => {
  let config = env === "production" ? productionConfig : developmentConfig;
  return merge(commonConfig, config); // Merging public and environmental configurations
};

4. How to distinguish different environments in code?

4.1 Profile

If this JS file is the entry file for the webpack command, such as build/webpack.common.conf.js, the value of mode (production or development) is automatically passed into the first parameter of module.exports, which developers can use directly.

In the following code, first determine what environment is, then decide what configuration to use, and finally return to webpack:

module.exports = env => {
  let config = env === "production" ? productionConfig : developmentConfig;
  return merge(commonConfig, config); // Merging public and environmental configurations
};

4.2 Project Document

If the js file is a script file in the project, you can access the process.env.NODE_ENV variable to determine the environment:

if (process.env.NODE_ENV === "development") {
  console.log("development environment");
} else {
  console.log("production environment");
}

5. Write configuration files

5.1 Writing Public Profiles

// /build/webpack.common.conf.js

const webpack = require("webpack");
const merge = require("webpack-merge");
const ExtractTextPlugin = require("extract-text-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

const path = require("path");

const productionConfig = require("./webpack.prod.conf.js"); // Introducing Production Environment Profile
const developmentConfig = require("./webpack.dev.conf.js"); // Introducing Development Environment Configuration Files

/**
 * Generate different configurations according to different environments
 * @param {String} env "development" or "production"
 */
const generateConfig = env => {
  // Separate declarations of Loader and Plugin will be required

  let scriptLoader = [
    {
      loader: "babel-loader"
    }
  ];

  let cssLoader = [
    {
      loader: "css-loader",
      options: {
        minimize: true,
        sourceMap: env === "development" ? true : false // Development environment: Open source-map
      }
    }
  ];

  let styleLoader =
    env === "production"
      ? ExtractTextPlugin.extract({
          // Production environment: separating and refining style files
          fallback: {
            loader: "style-loader"
          },
          use: cssLoader
        })
      : // Development Environment: Inside-page Style Embedding
        cssLoader;

  return {
    entry: { app: "./src/app.js" },
    output: {
      publicPath: env === "development" ? "/" : __dirname + "/../dist/",
      path: path.resolve(__dirname, "..", "dist"),
      filename: "[name]-[hash:5].bundle.js",
      chunkFilename: "[name]-[hash:5].chunk.js"
    },
    module: {
      rules: [
        { test: /\.js$/, exclude: /(node_modules)/, use: scriptLoader },
        { test: /\.css$/, use: styleLoader }
      ]
    },
    plugins: [
      // Plug-ins for both development and production environments
      new HtmlWebpackPlugin({
        filename: "index.html",
        template: path.resolve(__dirname, "..", "index.html"),
        chunks: ["app"],
        minify: {
          collapseWhitespace: true
        }
      }),
      new webpack.ProvidePlugin({ $: "jquery" })
    ]
  };
};

module.exports = env => {
  let config = env === "production" ? productionConfig : developmentConfig;
  return merge(generateConfig(env), config);
};

5.2 Writing Development Environment Profile

// /build/webpack.dev.conf.js

const webpack = require("webpack");

const path = require("path");

module.exports = {
  mode: "development",
  devtool: "source-map",
  devServer: {
    contentBase: path.join(__dirname, "../dist/"),
    port: 8000,
    hot: true,
    overlay: true,
    proxy: {
      "/comments": {
        target: "https://m.weibo.cn",
        changeOrigin: true,
        logLevel: "debug",
        headers: {
          Cookie: ""
        }
      }
    },
    historyApiFallback: true
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NamedModulesPlugin()
  ]
};

5.3 Writing Production Environment Profile

// /build/webpack.comm.conf.js

const ExtractTextPlugin = require("extract-text-webpack-plugin");
const CleanWebpackPlugin = require("clean-webpack-plugin");

const path = require("path");

module.exports = {
  mode: "production",
  plugins: [
    new ExtractTextPlugin({
      filename: "[name].min.css",
      allChunks: false // Include only initialization css, excluding asynchronously loaded CSS
    }),
    new CleanWebpackPlugin(["dist"], {
      root: path.resolve(__dirname, "../"),
      verbose: true
    })
  ]
};

6. Other documents

The sample files shown in the screenshot of the project catalog, the files under vendor and app.js, are not listed one by one. You can write some simple code according to your own needs, and then run it. After all, the architecture and explanations of the previous configuration files are the most important.

Only the source address is given here (welcome Star oh):

7. Operation effect and test

After a long time of drumming, I'm sure I'll have to test it, or how can I know the correctness (This is an exciting step).

7.1 Running: Development Model

Enter the project directory and run npm run dev:

Successful running, no mistakes (nonsense, are debugged many times, haha ha).

Open the browser's console and see:

Very good. They are all output according to the logic of app.js.

7.2 Running: Production Model

After exiting the development mode according to Ctrl+C, run npm run build and package successfully as follows:

The packaged files are also placed in the designated location:

Click index.html directly and open the browser console:

ok, in line with the output of app.js: successfully identified whether it is a development environment!!!?

8. finally

End the flower scattering (deg)

Posted by zurron on Fri, 10 May 2019 12:27:11 -0700