前端项目模块化的实践2:使用 Webpack 打包基础设施代码
以下是关于前端项目模块化的实践,包含以下内容:
使用 TypeScript 编写可靠类库 (实现中)
本文是关于前端项目模板化的第2部分
现状
实际项目远远比示例使用的 myGreeting 复杂,比如
为了提高可维护性我们将项目折成了许多功能模板;
我们希望使用 Promise 等语法等,但是顾忌目标环境的支持能力;
可能依赖了多个第三方类库;
为了提高加载速度我们打包时需要进行很多额外工作;
代码压缩;
Tree Shaking(参考文末);
既能运行在 WEB 浏览器,也能在 NodeJS 中使用;
假设我们有一个工具集项目 myHammer,包含 base64 转换功能和一个简单版的字典树实现,项目结构如下:
busybruce@DESKTOP-B8KJKRS /d/Documents/MyGit/PracticeInNPM/myHammer $ tree src/ test/ src/ ├── base64.js ├── index.js └── TrieFilter.jstest/ ├── base64.test.js └── TrieFilter.test.js 0 directories, 5 files
index.js
导出了项目中的功能模块:
const base64 = require('./base64');const TrieFilter = require('./TrieFilter')module.exports = { base64, TrieFilter, }
如果不打包,单独发布当前项目到 NPM 仓库并没有问题,只是
依赖本项目的时候写法比较纠结,形如
const base64 = require('myHammer/src/base64')
;可能存在到目标环境的适配问题,如前文所述;
目标环境不支持 Promise 等语法等
源码是 CoffeeScript 或者 TypeScript,没法直接引用
下面使用 Webpack 来解决这些问题。
Webpack 打包基础类库
Webpack 文档内容多,网上教程多是关于应用打包,现整理如下。
本文并非 Webpack 的使用指南,只提及类库打包,行文时Webpack已更新至4.x 版本。
package.json
需要配置 package.json
的 main
节点供 NodeJS 环境使用。
"main": "src/index.js",
NodeJS 运行环境作了约定,使用 require('xxx')
时将读取该配置。
避免形如
require('myHammer/src/base64')
类似的引用完整路径的写法如果源码使用了高版本的语言特性,可以转译和打包代码到形如
dist/inde-es5.js
的路径,再修改该配置指向该文件以向下兼容使用需要转译成 JavaScript 语言同理
在部分 IDE 时我们查找引用时,往往发现函数声明有好多处实现,原因就在于代码转译、打包成了很多份,如下图所示。
webpack.config.js
类库打包需要对 webpack.config.js
中的 output
进行配置,摘取如下:
output : { library : "hammer", libraryTarget: "umd", globalObject : "this", path : path.join(__dirname, "dist"), filename : "hammer.js", }
其他配置请自行阅读文档,完整内容见代码 webpack.config.js。
libraryTarget
: 为了在浏览器和 NodeJS 环境中同时生效,需要使用umd
作为目标,参考 output-librarytargetglobalObject
: 使用this
替换默认的window
,参考 Webpack 4.0.1 | WebWorkerwindow is not defined
#6642
如前文所述,在不考虑语言、版本、目标平台的差异的情况下,直接将源码发布到 NPM 仓库,再添加依赖和引用并无问题。在业务日益复杂的情况下,手写代码在实现层面直接消除这些差异是无比巨大的工作量,使用 Webpack 让我们更专注业务本身, Make life easier。
发布到 NPM 和使用依赖
在完成了具体业务后,我们打包项目并发布到私有 NPM 仓库
webpack --mode development # 视具体需求npm publish --registry http://ubuntu-17:4873 # --force
在 myDemo 项目中我们添加引用
yarn add myHammer --registry http://ubuntu-17:4873
修改 index.js
如下:
const myGreeting = require('myGreeting');const {base64} = require('myHammer'); (function () { let greeting = myGreeting('Rattz'); console.log(base64.encode(greeting)); })();
运行起来
$ node index.js SGVsbG8gUmF0dHo=
关于 Tree Shaking
略微提及一下 Tree Shaking ,简单地说 Tree Shaking 通过不引用没有依赖的代码,能有效缩减打包后的文件大小。
举例来说,我们使用了 ES2016 的语法,希望最后编译在 ES2015 环境使用。这里有若干种可行方案,其中一种是
使用 babel 全家桶包含
babel-cli, babel-core, babel-loader, babel-preset-env
;添加 .babelrc 文件写入内容
{"presets":["env"]}
;在入口代码的首行使用
require('babel-polyfill');
babel 进行语法转换,补丁文件进行对低版本 ES2015 的适配,该方案中 babel-polyfill
被完整引用, 打包完成后占用120k 左右大小,往往比业务代码还多。
Tree Shaking 即为解决该问题而来,比如某模板同时提供了加法和减法,而我们只依赖了加法方法,如果打包工具支持 Tree Shaking,就能在打包时剔除掉未使用的减法相关代码。
Webpack 提供了相关支持,见于 Tree Shaking - webpack。
项目所使用源码已发布 github,jusfrw 原创
原文出处:https://www.cnblogs.com/Jusfr/p/9551119.html
共同学习,写下你的评论
评论加载中...
作者其他优质文章