用webpack写个当代的JavaScript包

webpack 作为如今主流的构建东西,其较快的版本迭代和庞杂的设置体式格局,使得每次开辟前不能不计划相称部份时刻来调试。这里将纪录全部环境的搭建历程,为新手供应基础思绪。

就像我在开辟vue-sitemap时一样,构建东西每每须要到达下面几个需求:

  • 构建天生 CommonJS/UMD/ES Modules 三种形式的代码供应给运用者
  • 需运转测试和搜检测试掩盖的进度
  • 开辟时刻运用 VS Code 编辑器举行断点调试

以上三个作为开辟一个组件(package)是基础中基础的需求,固然另有更多细节内容须要增添,由于篇幅太长另加文章再说吧。(迎接列位读者批评留下你以为须要的功用( • ̀ω•́ )✧)

第一步:构建东西

接下来我们先从最基础的最先,须要装置 Node.js(10.x) 作为一切代码的运转环境, webpack 也是一样。

初始化项目

由于我须要把项目宣布至 npm 的,运用敕令初始化项目形貌文件 package.json

npm init

首次化细节列位读者找其他文章补全吧,这里不细说

接下来看看目次构造

│  package.json     //项目形貌文件
│  README.md        //GitHub建立堆栈时默许建立
├─src               //源代码目次
│      index.js     //进口文件
├─tests             //测试代码目次
│
├─dist              //临盆文件的目次
│
└─docs              //文档目次

增添 webpack

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

这里运用的 webpack v4,后续设置也是基于4来设置,
cross-env是协助在 win 下能一般运用环境变量的包,我开辟在 win 环境因而在这加上。

yarn 是一款疾速、牢靠、平安的依靠治理东西。假如你以为 npm 装置时刻较慢的话,无妨尝尝。

等依靠下载处置惩罚终了以后,,在package.json设置构建敕令轻易以后运用。

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

这里我们能够尝试运转一下敕令npm run build尝试可否构建胜利,胜利的状况下在dist目次下会天生main.js的文件。

设置 webpack

建立 webpack.config.js文件来设置 webpack 。为满足我们的第一个须要天生三种形式的代码:

//# webpack.config.js

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")
        }
    }
}

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

增添构建敕令

package.json 增添新的运转敕令

//# package.json
{
  "version": "0.1.0",
  "name": "vscode-mocha-webpack-example",
  "description": "用于治理导航、面包屑及路由等基于vue的功用整合",
  "main": "./src/index.js",
  "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"
  }
  ...
}

运转npm run build就会 CommonJS/UMD/ES Modules 三种形式天生对应的文件。

也许是这模样:

├─dist
│    vscode-mocha-webpack-example.common.js
│    vscode-mocha-webpack-example.es.js
│    vscode-mocha-webpack-example.min.js
│    vscode-mocha-webpack-example.js

指定终端

为了使你的构建文件成为终究宣布包的一部份,你必需声明它们。将以下内容增添到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"
],
  • files部份通知npm在宣布时打包这些文件夹(不然,它们将被疏忽,由于它们列在.gitignore文件中)
  • main定义CommonJS构建的终端
  • jsnext:mainmodule定义了ES2015构建的终端(我们定义了两个终端,由于jsnext:main是最早运用的范例,而module则更相符标准范例)。

第二步,设置babel

经由过程 babel 使得我们运用最新的语法,而没必要忧郁运转环境不支撑的题目。在webpack的下我们须要用到babel-loader来导入babel支撑,关于最新的兼容设置还需运用上babel-preset-env

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

建立 babel 设置文件

接着在.babelrc文件里设置babel兼容的划定规矩:

{
    "presets": [
        [
            "env",
            {
                "useBuiltIns": false,
                "modules": false
            }
        ]
    ]
}

为 webpack 增添 babel-loader

当我们运用最新语法编写 JavaScript 时,webpack 会婚配将一切 JS 文件给 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 = config

当运转构建时webpack便会加载babel及其相干的设置将代码转换并天生,到这步构建相干的设置基础完成。

第三步,增添自动化测试

置信对自动化测试有所相识的读者应当对mocha并不生疏,不相识的能够先去补补相干学问再往下看。简朴的测试较多运用mocha来举行处置惩罚,另有断言库chai和供应promise支撑的chai-as-promised等等,下面先把这些依靠装置上:

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

测试代码想运用es新特征时能够运用
mocha-webpack这个插件。

然后在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"
    }
    //...
}

.babelrc 也须要设置一下:

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

为了能测试增添tests/unit/example.spec.jssrc/index.js两个文件,代码以下:

├─src
│      index.js
└─tests
    └─unit
            example.spec.js
//# 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") });
})

如今运转测试敕令就可以得出测试结果了:

npm run test

也许输出是这个模样:

 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

关于测试掩盖率的题目

有了测试还得晓得测试是不是都掩盖了一切代码(据说基础要到80%,有些团队能够请求更高90~95%),那怎样得知?

nyc这个包就可以协助到我去磨练测试掩盖率,起首先装置依靠:

npm install -D nyc babel-plugin-istanbul

再设置搜检局限和增添敕令:

//# 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
    }
    ...
}

装置依靠中也看到babel也须要增添相干的设置:

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

运转npm run test将会取得以下内容:

 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 |                   |
----------|----------|----------|----------|----------|-------------------|

简朴说一下这四栏东西代表什么意思:

  • Stmts : Statement coverage 声明掩盖率,顺序中的每一个语句都已实行吗?
  • Branch: Branch coverage 分支掩盖率,是不是已实行每一个掌握构造的每一个分支(也称为DD途径)(比方if和case语句)?比方,给定if语句,是不是已实行true和false分支?
  • Funcs: Function coverage 要领掩盖率,是不是已挪用顺序中的每一个函数(或子例程)?
  • Lines: Line coverage 行代码掩盖,是不是已实行源文件中的每一个可实行的行?

不在掩盖局限内的代码的行数会在Uncovered Line这栏显现。

为测试供应async/await支撑

在测试中想运用async/await语法,需新增setup.js文件并在进口处增添babel-polyfill

require("babel-polyfill");

并在.babelrc修正useBuiltInsentry

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

接下来在src/index.jstests/example.spec.js两个文件增添新的代码:

//# src/index.js
export function getUsers(){
    return new Promise((resolve, reject)=>{
        setTimeout(()=>{
            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]");
  })
})

运转测试就可以看到结果!

让测试更进一步,在 VS Code 中调试

想在VS Code断点调试代码须要分外增添一些设置,增添以下代码至 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;

在VS Code 增添调试代码

翻开 VS Code 调试面板在下拉选项中挑选增添设置(或许直接建立并翻开.vscode/launch.json文件):


// 运用 IntelliSense 相识相干属性。
// 悬停以检察现有属性的形貌。
// 欲相识更多信息,请接见: 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"
    }]
}

src目次下的源代码或是tests目次下的测试代码都能取得断点结果,想立时尝试能够下载本文例子vscode-mocha-webpack-example,装置依靠后就可以尝试断点调试了。

设置参考源自
vscode-ts-webpack-node-debug-example

值得一提的是,上面参考例子原文说devtool运用eval相干的设置并不能断点,然则在运用mocha-webpack调试时上面例子并不能完成断点。在我和公司小伙伴多番寻觅vscodemocha-webpack的issue后,经由种种尝试下发明设置成eval-source-map便能完成最好断点结果(eval也能完成然则由于断点sourcemap指向的源是天生后的文件致使在断点时若干会发生偏移)。

吐槽:在运用
nvm切换
nodejs环境时发明
npm下载不了,翻开github的下载链接直接404了,惊悚地发明
npm全部搬走 (`Д´*)9 ┴┴,为处置惩罚这个题目请下载最新版本
v1.1.7
nvm

末了:

我的动力来自你的指头,请用你的指头用力给我个赞吧!d(´ω` )

以为本文有协助的话不要遗忘点一下珍藏φ(>ω<*) 哦!

同时迎接各路新手、大神在本文下方吐槽留言,感谢介入议论的列位仁兄!( • ̀ω•́ )✧

下面是本文完全例子,记得star一下!

同时非常感谢
Mather协同编辑!

    原文作者:帕奇式
    原文地址: https://segmentfault.com/a/1190000017154225
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞