{"id":20139235,"url":"https://github.com/lpreterite/vscode-mocha-webpack-example","last_synced_at":"2026-05-06T15:33:14.851Z","repository":{"id":81486153,"uuid":"158673719","full_name":"lpreterite/vscode-mocha-webpack-example","owner":"lpreterite","description":"用webpack写个现代的JavaScript包","archived":false,"fork":false,"pushed_at":"2018-11-27T02:28:16.000Z","size":87,"stargazers_count":0,"open_issues_count":0,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-13T10:11:28.776Z","etag":null,"topics":["mocha","mocha-webpack","vscode","webpack","webpack4"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lpreterite.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-11-22T09:23:55.000Z","updated_at":"2018-11-27T02:28:18.000Z","dependencies_parsed_at":null,"dependency_job_id":"4732519a-5d2a-4402-b76d-007fcab4d912","html_url":"https://github.com/lpreterite/vscode-mocha-webpack-example","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lpreterite%2Fvscode-mocha-webpack-example","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lpreterite%2Fvscode-mocha-webpack-example/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lpreterite%2Fvscode-mocha-webpack-example/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lpreterite%2Fvscode-mocha-webpack-example/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lpreterite","download_url":"https://codeload.github.com/lpreterite/vscode-mocha-webpack-example/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241582557,"owners_count":19985846,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["mocha","mocha-webpack","vscode","webpack","webpack4"],"created_at":"2024-11-13T21:44:30.950Z","updated_at":"2026-05-06T15:33:09.819Z","avatar_url":"https://github.com/lpreterite.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 用webpack写个现代的JavaScript包\n\n[webpack](https://webpack.js.org/) 作为目前主流的构建工具，其较快的版本迭代和复杂的配置方式，使得每次开发前不得不规划相当部分时间来调试。这里将记录整个环境的搭建过程，为新手提供基础思路。\n\n就像我在开发`vue-sitemap`时一样，构建工具往往需要达到下面几个需求：\n\n- 构建生成 CommonJS/UMD/ES Modules 三种模式的代码提供给使用者\n- 需运行测试和检查测试覆盖的进度\n- 开发时候使用 [VS Code](https://code.visualstudio.com/) 编辑器进行断点调试\n\n\n以上三个作为开发一个组件(`package`)是基础中基础的需求，当然还有更多细节内容需要添加，由于篇幅过长另加文章再说吧。（欢迎各位读者评论留下你认为需要的功能( • ̀ω•́ )✧）\n\n## 第一步：构建工具\n\n接下来我们先从最基础的开始，需要安装 [Node.js(10.x)](https://nodejs.org/zh-cn/) 作为所有代码的运行环境， webpack 也是一样。\n\n### 初始化项目\n\n由于我需要把项目发布至 npm 的，使用命令初始化项目描述文件 `package.json`\n\n```sh\nnpm init\n```\n\n\u003e 初次化细节各位读者找其他文章补全吧，这里不细说\n\n接下来看看目录结构\n\n```txt\n│  package.json     //项目描述文件\n│  README.md        //GitHub创建仓库时默认创建\n├─src               //源代码目录\n│      index.js     //入口文件\n├─tests             //测试代码目录\n│\n├─dist              //生产文件的目录\n│\n└─docs              //文档目录\n```\n\n### 添加 webpack\n\n```sh\nnpm install -D webpack webpack-cli cross-env\n//or\n//yarn add webpack webpack-cli cross-env -D\n```\n\n\u003e 这里使用的 webpack v4，后续设置也是基于4来设置，`cross-env`是帮助在 win 下能正常使用环境变量的包，我开发在 win 环境于是在这加上。\n\n\u003e [yarn](https://www.yarnpkg.com/zh-Hans/) 是一款快速、可靠、安全的依赖管理工具。如果你觉得 npm 安装时候较慢的话，不妨试试。\n\n\n等依赖下载解决完毕之后，，在`package.json`设置构建命令方便之后使用。\n\n```json\n//# package.json\n{\n  //...\n  \"scripts\": {\n    \"build\": \"cross-env NODE_ENV=production webpack --propress --hide-modules\",\n  }\n}\n```\n\n这里我们可以尝试运行一下命令`npm run build`尝试能否构建成功，成功的情况下在`dist`目录下会生成`main.js`的文件。\n\n### 配置 webpack\n\n创建 `webpack.config.js`文件来配置 webpack 。为满足我们的第一个需要生成三种模式的代码：\n\n```js\n//# webpack.config.js\n\nconst package = require('./package.json')\nconst path = require('path')\n\nconst config = {\n    entry: \"./src/index.js\",  //入口文件\n    output: {                 //输出设置\n        path: path.resolve(__dirname, \"./dist\"),\n        filename: `${package.name}.js`\n    },\n    resolve: {\n        alias: {\n            \"@\": path.resolve(__dirname, \"./src\")\n        }\n    }\n}\n\nif (process.env.NODE_ENV === \"umd\") {\n    config.optimization = { minimize: false };\n    config.output.library = package.name;\n    config.output.libraryTarget = \"umd2\";\n    config.output.filename = `${package.name}.js`;\n}\nif (process.env.NODE_ENV === \"umd:min\") {\n    config.output.library = package.name;\n    config.output.libraryTarget = 'umd2';\n    config.output.filename = `${package.name}.min.js`;\n}\nif (process.env.NODE_ENV === \"es\") {\n    config.output.library = package.name;\n    config.output.libraryTarget = \"amd\";\n    config.output.filename = `${package.name}.es.js`;\n}\nif (process.env.NODE_ENV === \"commonjs\") {\n    config.output.library = package.name;\n    config.output.libraryTarget = \"commonjs2\";\n    config.output.filename = `${package.name}.common.js`;\n}\n\nmodule.exports = config\n```\n\n### 添加构建命令\n\n为 `package.json` 添加新的运行命令\n\n```json\n//# package.json\n{\n  \"version\": \"0.1.0\",\n  \"name\": \"vscode-mocha-webpack-example\",\n  \"description\": \"用于管理导航、面包屑及路由等基于vue的功能整合\",\n  \"main\": \"./src/index.js\",\n  \"scripts\": {\n    \"build\": \"npm run build:commonjs \u0026\u0026 npm run build:es \u0026\u0026 npm run build:umd \u0026\u0026 npm run build:umd:min\",\n    \"build:umd\": \"cross-env NODE_ENV=umd webpack --mode=production --progress --hide-modules\",\n    \"build:umd:min\": \"cross-env NODE_ENV=umd:min webpack --mode=production --progress --hide-modules\",\n    \"build:es\": \"cross-env NODE_ENV=es webpack --mode=production --progress --hide-modules\",\n    \"build:commonjs\": \"cross-env NODE_ENV=commonjs webpack --mode=production --progress --hide-modules\"\n  }\n  ...\n}\n```\n\n运行`npm run build`就会 CommonJS/UMD/ES Modules 三种模式生成对应的文件。\n\n大概是这样子：\n\n```txt\n├─dist\n│    vscode-mocha-webpack-example.common.js\n│    vscode-mocha-webpack-example.es.js\n│    vscode-mocha-webpack-example.min.js\n│    vscode-mocha-webpack-example.js\n```\n\n### 指定终端\n\n为了使你的构建文件成为最终发布包的一部分，你必须声明它们。将以下内容添加到package.json：\n\n```json\n\"main\": \"dist/vscode-mocha-webpack-example.common.js\",\n\"module\": \"dist/vscode-mocha-webpack-example.es.js\",\n\"jsnext:main\": \"dist/vscode-mocha-webpack-example.es.js\",\n\"files\": [\n  \"dist\",\n  \"src\"\n],\n```\n\n- `files`部分告诉npm在发布时打包这些文件夹（否则，它们将被忽略，因为它们列在`.gitignore`文件中）\n- `main`定义CommonJS构建的终端\n- `jsnext:main`和`module`定义了ES2015构建的终端（我们定义了两个终端，因为`jsnext:main`是最早使用的规范，而`module`则更符合标准规范）。\n\n## 第二步，设置babel\n\n通过 `babel` 使得我们使用最新的语法，而不必担心运行环境不支持的问题。在`webpack`的下我们需要用到`babel-loader`来导入`babel`支持，关于最新的兼容设置还需使用上`babel-preset-env`：\n\n```sh\nnpm install -D babel babel-cli babel-preset-env\n//or\n//yarn add babel babel-cli babel-preset-env -D\n```\n\n### 创建 babel 配置文件\n\n接着在`.babelrc`文件里设置babel兼容的规则：\n\n```json\n{\n    \"presets\": [\n        [\n            \"env\",\n            {\n                \"useBuiltIns\": false,\n                \"modules\": false\n            }\n        ]\n    ]\n}\n```\n\n### 为 webpack 添加 babel-loader\n\n当我们使用最新语法编写 JavaScript 时，webpack 会匹配将所有 JS 文件给 `babel` 的处理。\n\n```js\nconst package = require('./package.json')\nconst path = require('path')\n\nconst config = {\n    entry: \"./src/index.js\",\n    output: {\n        path: path.resolve(__dirname, \"./dist\"),\n        filename: `${package.name}.js`\n    },\n    resolve: {\n        alias: {\n            \"@\": path.resolve(__dirname, \"./src\")\n        }\n    },\n    module: {\n        rules: [\n            {\n                test: /\\.js$/,\n                loader: 'babel-loader',\n                exclude: /node_modules/\n            }\n        ]\n    }\n}\n\n...\n\nmodule.exports = config\n```\n\n当运行构建时`webpack`便会加载`babel`及其相关的设置将代码转换并生成，到这步构建相关的设置基本完成。\n\n## 第三步，添加自动化测试\n\n相信对自动化测试有所了解的读者应该对`mocha`并不陌生，不了解的可以先去补补相关知识再往下看。简单的测试较多使用`mocha`来进行处理，还有断言库`chai`和提供promise支持的`chai-as-promised`等等，下面先把这些依赖安装上：\n\n```sh\nnpm install -D mocha mocha-webpack chai chai-as-promised\n//or\n//yarn add mocha mocha-webpack chai chai-as-promised -D\n```\n\n\u003e 测试代码想使用es新特性时可以使用`mocha-webpack`这个插件。\n\n然后在`package.json`添加上测试命令：\n\n```json\n{\n    //...\n    \"scripts\": {\n        \"build\": \"npm run build:commonjs \u0026\u0026 npm run build:es \u0026\u0026 npm run build:umd \u0026\u0026 npm run build:umd:min\",\n        \"build:umd\": \"cross-env NODE_ENV=umd webpack --mode=production --progress --hide-modules\",\n        \"build:umd:min\": \"cross-env NODE_ENV=umd:min webpack --mode=production --progress --hide-modules\",\n        \"build:es\": \"cross-env NODE_ENV=es webpack --mode=production --progress --hide-modules\",\n        \"test\": \"cross-env NODE_ENV=test mocha-webpack tests/**/*.spec.js\"\n    }\n    //...\n}\n```\n\n`.babelrc` 也需要设置一下：\n\n```json\n{\n    //...\n    \"env\": {\n        \"test\": {\n            \"presets\": [\n                [\n                    \"env\",\n                    {\n                        \"modules\": false,\n                        \"targets\": {\n                            \"node\": \"current\"\n                        }\n                    }\n                ]\n            ]\n        }\n    }\n}\n```\n\n为了能测试添加`tests/unit/example.spec.js`和`src/index.js`两个文件，代码如下：\n\n```text\n├─src\n│      index.js\n└─tests\n    └─unit\n            example.spec.js\n\n```\n\n\n```js\n//# src/index.js\nexport function getRole(user){\n    switch(user){\n        case \"Packy\":\n            return \"admin\"\n        case \"Joan\":\n            return \"reader\"\n    }\n}\n\n//# tests/unit/example.spec.js\nimport { assert } from \"chai\";\nimport { getRole } from \"@/index\";\n\ndescribe('Testing', ()=\u003e{\n  it('Packy is admin', () =\u003e { assert.equal(getRole('Packy'), 'admin') })\n  it(\"Joan is reader\", () =\u003e { assert.equal(getRole(\"Joan\"), \"reader\") });\n})\n```\n\n现在运行测试命令就能得出测试结果了：\n\n```sh\nnpm run test\n```\n\n大概输出是这个样子：\n\n```txt\n WEBPACK  Compiling...\n\n  [=======================  ] 91% (additional chunk assets processing)\n WEBPACK  Compiled successfully in 5893ms\n\n MOCHA  Testing...\n\n\n\n  Testing\n    √ Packy is admin\n    √ Joan is reader\n\n\n  2 passing (39ms)\n\n MOCHA  Tests completed successfully\n```\n\n### 关于测试覆盖率的问题\n\n有了测试还得知道测试是否都覆盖了所有代码（听说基本要到80%，有些团队可能要求更高90~95%），那如何得知？\n\n`nyc`这个包就能帮助到我去检验测试覆盖率，首先先安装依赖：\n\n```sh\nnpm install -D nyc babel-plugin-istanbul\n```\n\n再设置检查范围和添加命令：\n\n```json\n//# package.json\n{\n    ...\n    \"scripts\": {\n        \"build\": \"npm run build:commonjs \u0026\u0026 npm run build:es \u0026\u0026 npm run build:umd \u0026\u0026 npm run build:umd:min\",\n        \"build:umd\": \"cross-env NODE_ENV=umd webpack --mode=production --progress --hide-modules\",\n        \"build:umd:min\": \"cross-env NODE_ENV=umd:min webpack --mode=production --progress --hide-modules\",\n        \"build:es\": \"cross-env NODE_ENV=es webpack --mode=production --progress --hide-modules\",\n        \"build:commonjs\": \"cross-env NODE_ENV=commonjs webpack --mode=production --progress --hide-modules\",\n        \"test\": \"cross-env NODE_ENV=test nyc mocha-webpack tests/**/*.spec.js\"\n    },\n    ...\n    \"nyc\": {\n        \"include\": [\n            \"src/**\"\n        ],\n        \"instrument\": false,\n        \"sourceMap\": false\n    }\n    ...\n}\n```\n\n安装依赖中也看到`babel`也需要添加相关的设置：\n\n```json\n//# .babelrc\n{\n    ...\n    \"env\": {\n        \"test\": {\n            \"presets\": [\n                [\n                    \"env\",\n                    {\n                        \"modules\": false,\n                        \"targets\": {\n                            \"node\": \"current\"\n                        }\n                    }\n                ]\n            ],\n            \"plugins\": [\n                \"istanbul\"\n            ]\n        }\n    }\n}\n```\n\n运行`npm run test`将会得到以下内容：\n\n```txt\n WEBPACK  Compiling...\n\n  [=======================  ] 91% (additional chunk assets processing)\n WEBPACK  Compiled successfully in 5893ms\n\n MOCHA  Testing...\n\n\n\n  Testing\n    √ Packy is admin\n    √ Joan is reader\n\n\n  2 passing (39ms)\n\n MOCHA  Tests completed successfully\n\n----------|----------|----------|----------|----------|-------------------|\nFile      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |\n----------|----------|----------|----------|----------|-------------------|\nAll files |      100 |      100 |      100 |      100 |                   |\n index.js |      100 |      100 |      100 |      100 |                   |\n----------|----------|----------|----------|----------|-------------------|\n```\n\n简单说一下这四栏东西代表什么意思：\n\n- Stmts : `Statement coverage` 声明覆盖率，程序中的每个语句都已执行吗？\n- Branch: `Branch coverage` 分支覆盖率，是否已执行每个控制结构的每个分支（也称为DD路径）（例如if和case语句）？例如，给定if语句，是否已执行true和false分支？\n- Funcs: `Function coverage` 方法覆盖率，是否已调用程序中的每个函数（或子例程）？\n- Lines: `Line coverage` 行代码覆盖，是否已执行源文件中的每个可执行的行？\n\n不在覆盖范围内的代码的行数会在`Uncovered Line`这栏显示。\n\n### 为测试提供async/await支持\n\n在测试中想使用async/await语法，需新增setup.js文件并在入口处添加`babel-polyfill`：\n\n```js\nrequire(\"babel-polyfill\");\n```\n\n并在`.babelrc`修改`useBuiltIns`为`entry`：\n\n```json\n{\n    ...\n    \"env\": {\n        \"test\": {\n            \"presets\": [\n                [\n                    \"env\",\n                    {\n                        \"useBuiltIns\": \"entry\",\n                        \"modules\": false,\n                        \"targets\": {\n                            \"node\": \"current\"\n                        }\n                    }\n                ]\n            ],\n            \"plugins\": [\n                \"istanbul\"\n            ]\n        }\n    }\n}\n```\n\n接下来在`src/index.js`和`tests/example.spec.js`两个文件添加新的代码：\n\n```js\n//# src/index.js\nexport function getUsers(){\n    return new Promise((resolve, reject)=\u003e{\n        setTimeout(()=\u003e{\n            console.log('123')\n            resolve(['Packy', 'Joan'])\n        }, 1000)\n    })\n}\n\n//# tests/unit/example.spec.js\ndescribe('GetUsers', ()=\u003e{\n  it('get result is Array', async ()=\u003e{\n    const users = await getUsers();\n    assert.isArray(users, \"[message]\");\n  })\n})\n```\n\n运行测试就能看到效果！\n\n## 让测试更进一步，在 VS Code 中调试\n\n想在VS Code断点调试代码需要额外增加一些设置，添加以下代码至 `webpack.config.js`。\n\n```js\n//# webpack.config.js\n\n//...\n\nif (process.env.NODE_ENV === \"test\") {\n    config.devtool = \"eval-source-map\";\n    config.output = Object.assign(config.output, {\n        devtoolModuleFilenameTemplate: \"[absolute-resource-path]\",\n        devtoolFallbackModuleFilenameTemplate: '[absolute-resource-path]?[hash]'\n    });\n}\n\nmodule.exports = config;\n```\n\n### 在VS Code 添加调试代码\n\n打开 VS Code 调试面板在下拉选项中选择添加配置（或者直接创建并打开`.vscode/launch.json`文件）：\n\n```json\n\n// 使用 IntelliSense 了解相关属性。\n// 悬停以查看现有属性的描述。\n// 欲了解更多信息，请访问: https://go.microsoft.com/fwlink/?linkid=830387\n{\n    \"version\": \"0.2.0\",\n    \"configurations\": [\n    {\n        \"type\": \"node\",\n        \"request\": \"launch\",\n        \"name\": \"Mocha-webpack Tests\",\n        \"program\": \"${workspaceFolder}/node_modules/mocha-webpack/bin/mocha-webpack\",\n        \"args\": [\n            \"--full-trace\",\n            \"--timeout\",\n            \"999999\",\n            \"--colors\",\n            \"tests/**/*.js\"\n        ],\n        \"sourceMaps\": true,\n        \"env\": {\n            \"NODE_ENV\": \"test\"\n        },\n        \"internalConsoleOptions\": \"openOnSessionStart\"\n    }]\n}\n```\n\n在`src`目录下的源代码或是`tests`目录下的测试代码都能获得断点效果，想马上尝试可以下载本文例子[vscode-mocha-webpack-example](https://github.com/lpreterite/vscode-mocha-webpack-example)，安装依赖后就能尝试断点调试了。\n\n\u003e 设置参考源自[vscode-ts-webpack-node-debug-example](https://github.com/kube/vscode-ts-webpack-node-debug-example)\n\n值得一提的是，上面参考例子原文说`devtool`使用`eval`相关的设置并不能断点，但是在使用`mocha-webpack`调试时上面例子并不能实现断点。在我和公司小伙伴多番寻找`vscode`和`mocha-webpack`的issue后，经过各种尝试下发现设置成`eval-source-map`便能实现最佳断点效果（eval也能实现但是由于断点sourcemap指向的源是生成后的文件导致在断点时多少会产生偏移）。\n\n\u003e 吐槽：在使用`nvm`切换`nodejs`环境时发现`npm`下载不了，打开github的下载链接直接404了，惊悚地发现`npm`整个搬走 (\\`Д´*)9 ┴┴，为解决这个问题请下载最新版本`v1.1.7`的`nvm`。\n\n最后：\n\n**我的动力来自你的指头，请用你的指头使劲给我个赞吧！d(´ω｀ )**\n\n**觉得本文有帮助的话不要忘记点一下收藏φ(\u003eω\u003c*) 哦！**\n\n**同时欢迎各路新手、大神在本文下方吐槽留言，谢谢参与讨论的各位仁兄！( • ̀ω•́ )✧**\n\n下面是本文完整例子，记得star一下！\n\n- [vscode-mocha-webpack-example](https://github.com/lpreterite/vscode-mocha-webpack-example)\n\n\u003e 同时非常感谢[Mather](https://github.com/409915016)协同编辑！","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flpreterite%2Fvscode-mocha-webpack-example","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flpreterite%2Fvscode-mocha-webpack-example","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flpreterite%2Fvscode-mocha-webpack-example/lists"}