As the mainstream construction tool at present, WebPack has to plan a considerable amount of time for debugging before each development due to its rapid version iteration and complex configuration mode. The entire environment setup process will be recorded here to provide basic ideas for beginners.

Just like when I was developing Vue-Sitemap, the build tool often needs to meet the following requirements:

  • Build code that generates CommonJS/UMD/ES Modules for the user
  • Tests need to be run and progress of test coverage checked
  • Use VS Code editor for breakpoint debugging during development

The above three are the basic requirements for developing a package. Of course, there are more details to be added, but I will add them in another article because it is too long. (Readers are welcome to comment on the features you think are needed (• ̀ω•́)✧)

Step 1: Build the tools

We’ll start with the basics. We’ll need to install Node.js(10.x) as the environment to run all of our code, as well as WebPack.

Initialize the project

Since I need to publish the project to NPM, use the command to initialize the project description file package.json

npm init
Copy the code

For the first time the details of each reader to find other articles to fill it, here is not detailed

Now look at the directory structure

│ ├─ SRC // Source directory │ ├─ js // Import file ├─tests // Test code directory │ ├─dist ├ ─ garbage // ├ ─ garbage //Copy the code

Add webpack

npm install -D webpack webpack-cli cross-env
//or
//yarn add webpack webpack-cli cross-env -D
Copy the code

Webpack V4 is used here, and subsequent Settings are also based on 4. Cross-env is a package to help normal use of environment variables in Win, which I developed in Win and added here.

Yarn is a fast, reliable, and secure dependency management tool. If you find NPM slow to install, try it.

After the dependency download is resolved, use the package.json setup build command after it is convenient.

//# package.json
{
  //...
  "scripts": {
    "build": "cross-env NODE_ENV=production webpack --propress --hide-modules",
  }
}
Copy the code

Here we can run the command NPM run build to see if the build succeeds. If it succeeds, the main. Js file will be generated in the dist directory.

Configuration webpack

Create the webpack.config.js file to configure webpack. To satisfy our first need, generate code for three patterns:

//# webpack.config.js

const package = require('./package.json')
const path = require('path')

const config = {
    entry: "./src/index.js".// Import file
    output: {                 // Output Settings
        path: path.resolve(__dirname, "./dist"),
        filename: `${package.name}.js`
    },
    resolve: {
        alias: {
            "@": path.resolve(__dirname, "./src")}}}if (process.env.NODE_ENV === "umd") {
    config.optimization = { minimize: false };
    config.output.library = package.name;
    config.output.libraryTarget = "umd2";
    config.output.filename = `${package.name}.js`;
}
if (process.env.NODE_ENV === "umd:min") {
    config.output.library = package.name;
    config.output.libraryTarget = 'umd2';
    config.output.filename = `${package.name}.min.js`;
}
if (process.env.NODE_ENV === "es") {
    config.output.library = package.name;
    config.output.libraryTarget = "amd";
    config.output.filename = `${package.name}.es.js`;
}
if (process.env.NODE_ENV === "commonjs") {
    config.output.library = package.name;
    config.output.libraryTarget = "commonjs2";
    config.output.filename = `${package.name}.common.js`;
}

module.exports = config
Copy the code

Adding build commands

Add a new run command for package.json

//# package.json {"version": "0.1.0", "name": "vscode-mocha-webpack-example", "description": / SRC /index.js", "scripts": {"build": {"build": "npm run build:commonjs && npm run build:es && npm run build:umd && npm run build:umd:min", "build:umd": "cross-env NODE_ENV=umd webpack --mode=production --progress --hide-modules", "build:umd:min": "cross-env NODE_ENV=umd:min webpack --mode=production --progress --hide-modules", "build:es": "cross-env NODE_ENV=es webpack --mode=production --progress --hide-modules", "build:commonjs": "cross-env NODE_ENV=commonjs webpack --mode=production --progress --hide-modules" } ... }Copy the code

Run NPM run build to generate files in CommonJS/UMD/ES Modules.

Something like this:

├─dist │ vscode-mocha-webPack-example.common.js │ vscode-mocha-webpack-example.es.js │ ├─dist │ vscode-mocha-webpack-example.es.js │ Vscode - mocha - webpack - example. Min. Js │ vscode mocha - webpack - example. JsCopy the code

Specifies the terminal

In order for your build files to be part of the final release package, you must declare them. Add the following to package.json:

"main": "dist/vscode-mocha-webpack-example.common.js",
"module": "dist/vscode-mocha-webpack-example.es.js",
"jsnext:main": "dist/vscode-mocha-webpack-example.es.js",
"files": [
  "dist",
  "src"
],
Copy the code
  • filesThe section tells NPM to package these folders at release time (otherwise, they will be ignored because they are listed in.gitignoreFile)
  • mainDefine the CommonJS build terminal
  • jsnext:mainandmoduleDefines terminals for ES2015 builds (we defined two terminals becausejsnext:mainIs the earliest specification in use, whilemoduleIs more consistent with standard specifications).

Second, set up Babel

Babel allows us to use the latest syntax without having to worry about the runtime not supporting it. Use babel-loader to import Babel support in webpack, and use babel-preset-env for the latest compatibility Settings:

npm install -D babel babel-cli babel-preset-env
//or
//yarn add babel babel-cli babel-preset-env -D
Copy the code

Create the Babel configuration file

Then set the babel-compatible rules in the.babelrc file:

{
    "presets": [["env",
            {
                "useBuiltIns": false."modules": false}}]]Copy the code

Add babel-loader to Webpack

When we write JavaScript using the latest syntax, Webpack matches the processing of all JS files to Babel.

const package = require('./package.json')
const path = require('path')

const config = {
    entry: "./src/index.js".output: {
        path: path.resolve(__dirname, "./dist"),
        filename: `${package.name}.js`
    },
    resolve: {
        alias: {
            "@": path.resolve(__dirname, "./src")}},module: {
        rules: [{test: /\.js$/.loader: 'babel-loader'.exclude: /node_modules/}]}}... module.exports = configCopy the code

When you run the build, WebPack loads Babel and its associated Settings to transform and generate the code, and by this point, the building-related Settings are almost complete.

Third, add automated tests

For those of you who are familiar with automated testing, you should be familiar with Mocha. Simple tests are handled using Mocha, assertion library CHAI, and chai-as-promised, which provide promise support. Install these dependencies first:

npm install -D mocha mocha-webpack chai chai-as-promised
//or
//yarn add mocha mocha-webpack chai chai-as-promised -D
Copy the code

Mocha-webpack is a plugin for testing code that wants to use new ES features.

Then add the test command to package.json:

{
    //...
    "scripts": {
        "build": "npm run build:commonjs && npm run build:es && npm run build:umd && npm run build:umd:min",
        "build:umd": "cross-env NODE_ENV=umd webpack --mode=production --progress --hide-modules",
        "build:umd:min": "cross-env NODE_ENV=umd:min webpack --mode=production --progress --hide-modules",
        "build:es": "cross-env NODE_ENV=es webpack --mode=production --progress --hide-modules",
        "test": "cross-env NODE_ENV=test mocha-webpack tests/**/*.spec.js"
    }
    //...
}
Copy the code

.babelrc also needs to be set:

{
    //...
    "env": {
        "test": {
            "presets": [
                [
                    "env",
                    {
                        "modules": false,
                        "targets": {
                            "node": "current"
                        }
                    }
                ]
            ]
        }
    }
}
Copy the code

Add tests to test/unit/example. Spec. Js and SRC/index. The js two files, the code is as follows:

├─ SRC │ ├─ exercises ├─ unit example.specCopy the code
//# src/index.js
export function getRole(user){
    switch(user){
        case "Packy":
            return "admin"
        case "Joan":
            return "reader"}}//# tests/unit/example.spec.js
import { assert } from "chai";
import { getRole } from "@/index";

describe('Testing', ()=>{
  it('Packy is admin', () => { assert.equal(getRole('Packy'), 'admin') })
  it("Joan is reader", () => { assert.equal(getRole("Joan"), "reader")}); })Copy the code

Now run the test command to get the test result:

npm run test
Copy the code

The output might look something like this:

 WEBPACK  Compiling...

  [=======================  ] 91% (additional chunk assets processing)
 WEBPACK  Compiled successfully in 5893ms

 MOCHA  Testing...



  Testing
    √ Packy is admin
    √ Joan is reader


  2 passing (39ms)

 MOCHA  Tests completed successfully
Copy the code

Questions about test coverage

With tests, you also need to know if the tests cover all the code (I’ve heard it’s up to 80%, but some teams may require more than 90-95%). How do you know?

The nyc package will help me check test coverage by installing dependencies first:

npm install -D nyc babel-plugin-istanbul
Copy the code

Then set the check scope and add commands:

//# package.json
{
    ...
    "scripts": {
        "build": "npm run build:commonjs && npm run build:es && npm run build:umd && npm run build:umd:min",
        "build:umd": "cross-env NODE_ENV=umd webpack --mode=production --progress --hide-modules",
        "build:umd:min": "cross-env NODE_ENV=umd:min webpack --mode=production --progress --hide-modules",
        "build:es": "cross-env NODE_ENV=es webpack --mode=production --progress --hide-modules",
        "build:commonjs": "cross-env NODE_ENV=commonjs webpack --mode=production --progress --hide-modules",
        "test": "cross-env NODE_ENV=test nyc mocha-webpack tests/**/*.spec.js"
    },
    ...
    "nyc": {
        "include": [
            "src/**"
        ],
        "instrument": false,
        "sourceMap": false
    }
    ...
}
Copy the code

You can also see that Babel also needs to add related Settings:

//# .babelrc
{
    ...
    "env": {
        "test": {
            "presets": [
                [
                    "env",
                    {
                        "modules": false,
                        "targets": {
                            "node": "current"
                        }
                    }
                ]
            ],
            "plugins": [
                "istanbul"
            ]
        }
    }
}
Copy the code

Running NPM run test yields the following:

 WEBPACK  Compiling...

  [=======================  ] 91% (additional chunk assets processing)
 WEBPACK  Compiled successfully in 5893ms

 MOCHA  Testing...



  Testing
    √ Packy is admin
    √ Joan is reader


  2 passing (39ms)

 MOCHA  Tests completed successfully

----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |      100 |      100 |      100 |      100 |                   |
 index.js |      100 |      100 |      100 |      100 |                   |
----------|----------|----------|----------|----------|-------------------|
Copy the code

Here’s what these four columns mean:

  • Stmts : Statement coverageDeclare coverage. Is every statement in the program executed?
  • Branch: Branch coverageBranch coverage, is every branch (also known as DD path) of every control structure executed (such as if and case statements)? For example, given an if statement, have true and false branches been executed?
  • Funcs: Function coverageMethod coverage, is every function (or subroutine) in the program called?
  • Lines: Line coverageLine code coverage, has every executable line in the source file been executed?

The number of lines of code that are not covered will be shown in the Jude Line column.

Provide async/await support for tests

To use async/await syntax in your tests, add the setup.js file and add babel-polyfill at the entry:

require("babel-polyfill");
Copy the code

And change useBuiltIns to Entry in. Babelrc:

{... "env": { "test": { "presets": [ [ "env", { "useBuiltIns": "entry", "modules": false, "targets": { "node": "current" } } ] ], "plugins": [ "istanbul" ] } } }Copy the code

Add new code to SRC /index.js and tests/example.spec.js:

//# src/index.js
export function getUsers(){
    return new Promise((resolve, reject) = >{
        setTimeout((a)= >{
            console.log('123')
            resolve(['Packy'.'Joan'])},1000)})}//# tests/unit/example.spec.js
describe('GetUsers', ()=>{
  it('get result is Array'.async() = > {const users = await getUsers();
    assert.isArray(users, "[message]"); })})Copy the code

Run the test to see the results!

Take testing a step further and debug in VS Code

To debug VS Code breakpoints you need to add some extra Settings, add the following Code to webpack.config.js.

//# webpack.config.js

/ /...

if (process.env.NODE_ENV === "test") {
    config.devtool = "eval-source-map";
    config.output = Object.assign(config.output, {
        devtoolModuleFilenameTemplate: "[absolute-resource-path]".devtoolFallbackModuleFilenameTemplate: '[absolute-resource-path]? [hash]'
    });
}

module.exports = config;
Copy the code

Add debug Code in VS Code

Open the VS Code Debug panel and select Add Configuration from the drop down option (or create and open the.vscode/launch.json file directly) :

// Use IntelliSense to learn about related attributes. // Hover to view descriptions of existing properties. / / for more information, please visit: https://go.microsoft.com/fwlink/?linkid=830387 {" version ":" 0.2.0, "" configurations: [{" type" : "node", "request": "launch", "name": "Mocha-webpack Tests", "program": "${workspaceFolder}/node_modules/mocha-webpack/bin/mocha-webpack", "args": [ "--full-trace", "--timeout", "999999", "--colors", "tests/**/*.js" ], "sourceMaps": true, "env": { "NODE_ENV": "test" }, "internalConsoleOptions": "openOnSessionStart" }] }Copy the code

The breakpoint effect can be obtained from the source code in the SRC directory or from the tests directory. If you want to try it out, download vscode-mocha-webpack-example and install the dependency.

The setting reference is from vscode-ts-webpack-node-debug-example

It is worth noting that devTool does not have breakpoints with eval Settings, but it does not have breakpoints with mocha-Webpack debugging. After my company friends and I searched for the issue of vscode and mocha-webpack many times, After various attempts, it was found that eval-source-map worked best for breakpoints. (Eval also worked, but the breakpoint sourcemap was more or less offset at breakpoints because the source was the generated file.)

д ´*)9 ┴┴. To solve this problem, please download the latest version of NVM v1.1.7.

Finally:

My motivation comes from your fingers, please use your fingers hard to give me a thumbs-up! D (´ omega `)

Don’t forget to click favorites φ(>ω<*) oh!

At the same time, welcome all novices and gods to leave a comment at the bottom of this article. Thank you for participating in the discussion! ✧ (, ̀ omega, ́)

The following is a complete example of this article, remember star!

  • vscode-mocha-webpack-example

And a big thanks to Mather co-editor!