内容简介:webpack 作为目前主流的构建工具,其较快的版本迭代和复杂的配置方式,使得每次开发前不得不规划相当部分时间来调试。这里将记录整个环境的搭建过程,为新手提供基础思路。就像我在开发以上三个作为开发一个组件(
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:main
和module
定义了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.js
和 src/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 | | ----------|----------|----------|----------|----------|-------------------| 复制代码
简单说一下这四栏东西代表什么意思:
Statement coverage Branch coverage Function coverage Line coverage
不在覆盖范围内的代码的行数会在 Uncovered Line
这栏显示。
为测试提供async/await支持
在测试中想使用async/await语法,需新增setup.js文件并在入口处添加 babel-polyfill
:
require("babel-polyfill"); 复制代码
并在 .babelrc
修改 useBuiltIns
为 entry
:
{ ... "env": { "test": { "presets": [ [ "env", { "useBuiltIns": "entry", "modules": false, "targets": { "node": "current" } } ] ], "plugins": [ "istanbul" ] } } } 复制代码
接下来在 src/index.js
和 tests/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
调试时上面例子并不能实现断点。在我和公司小伙伴多番寻找 vscode
和 mocha-webpack
的issue后,经过各种尝试下发现设置成 eval-source-map
便能实现最佳断点效果(eval也能实现但是由于断点sourcemap指向的源是生成后的文件导致在断点时多少会产生偏移)。
吐槽:在使用 nvm
切换 nodejs
环境时发现 npm
下载不了,打开github的下载链接直接404了,惊悚地发现 npm
整个搬走 (`Д´*)9 ┴┴,为解决这个问题请下载最新版本 v1.1.7
的 nvm
。
最后:
我的动力来自你的指头,请用你的指头使劲给我个赞吧!d(´ω` )
觉得本文有帮助的话不要忘记点一下收藏φ(>ω<*) 哦!
同时欢迎各路新手、大神在本文下方吐槽留言,谢谢参与讨论的各位仁兄!( • ̀ω•́ )✧
下面是本文完整例子,记得star一下!
同时非常感谢 Mather 协同编辑!
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Fluent Python
Luciano Ramalho / O'Reilly Media / 2015-8-20 / USD 39.99
Learn how to write idiomatic, effective Python code by leveraging its best features. Python's simplicity quickly lets you become productive with it, but this often means you aren’t using everything th......一起来看看 《Fluent Python》 这本书的介绍吧!