前端项目模块化的实践2:使用 Webpack 打包基础设施代码
以下是关于前端项目模块化的实践,包含以下内容:
- 使用 TypeScript 的收益
- 使用 Mocha/Jest 进行单元测试 [实现中]
本文是关于前端项目模板化的第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.js
test/
├── 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 原创
前端项目模块化的实践2:使用 Webpack 打包基础设施代码的更多相关文章
- 前端项目模块化的实践3:使用 TypeScript 的收益
以下是关于前端项目模块化的实践,包含以下内容: 搭建 NPM 私有仓库管理源码及依赖: 使用 Webpack 打包基础设施代码: 使用 TypeScript 编写可靠类库 使用 TypeScript ...
- 前端项目模块化的实践1:搭建 NPM 私有仓库管理源码及依赖
以下是关于前端项目模块化的实践,包含以下内容: 搭建 NPM 私有仓库管理源码及依赖: 使用 Webpack 打包基础设施代码: 使用 TypeScript 编写可靠类库 使用 TypeScript ...
- 前端(以Vue为例)webpack打包后dist文件包如何部署到django后台中
由于现在前端使用的三大框架配合webpack可以实现快速打包,为部署到服务端提供了非常大的便利,那么在前端打包后,应该做些什么可以部署到django的后台中呢? 1.打包后文件包dist 进入到 di ...
- webpack打包es6代码
1.简单描述一下es6的模块导入和导出的语法: //导出:export var aa = 10;export function demo(){} //不能写成:var aa = 10;export a ...
- 简要分析webpack打包后代码
开门见山 1.打包单一模块 webpack.config.js module.exports = { entry:"./chunk1.js", output: { path: __ ...
- webpack打包样式代码去重
一.问题描述 控制台审查样式,同一个样式被导入很多遍,每调用一次@import "common.less";打包时都会多出一份类似的样式代码. 二.问题分析 补上... 三.解决方 ...
- nodejs 前端项目编译时内存溢出问题的原因及解决方案
现象描述 昨天用webpack打包Vue的项目时,node内存溢出而停止build项目,即是项目构建过程中频繁报内存溢出:FATAL ERROR: CALL_AND_RETRY_LAST Alloca ...
- 如何使用webpack打包项目
webpack是前端开发中比较常用的打包工具之一,另外还有gulp,grunt.之前没有涉及过打包这块,这里介绍一下使用webpack打包的流程. Grunt和Gulp的工作方式是:在一个配置文件中, ...
- 如何使用webpack打包你的项目
webpack是前端开发中比较常用的打包工具之一,另外还有gulp,grunt.之前没有涉及过打包这块,这里介绍一下使用webpack打包的流程. Grunt和Gulp的工作方式是:在一个配置文件中, ...
随机推荐
- 解决JBoss只能通过localhost访问不能通过IP的问题
前序 现在EJB是真的有点落伍了么,网上找点资料都挺难的样子,而且都是很久的了..好吧,最近对EJB有点兴趣学习一下,结果下载到服务器启动后,居然不能直接通过服务器IP访问,也是醉了,默认只能通过本地 ...
- jQuery为元素设置css的问题
例子: 有如下的html代码 对文本框设置字体大小为20px ,即font-size:20px 首先会想到如下: $('input').css({font-size:'20px'}); 由于属性不能使 ...
- Centos 6.5-yum安装出现错误解决方案
最近在用Centos 6.5 的时候出现了以下情况: 遇到这种问题试试以下方法: 1.检查是否能上网:ping www.baidu.com 如果显示没有连接的话,就说明没网,也就无法使用yum 命令安 ...
- C++类中的特殊成员函数-------复制构造函数
在C++中存在一个特殊函数,他就是复制构造函数,假如我们有类A,如果有A a;A b=a; 在这种情况下利用A类变量a来给同是A类变量的b来赋值,这个时候类会使用复制构造函数,如果我们不显式声明复 ...
- November 09th, 2017 Week 45th Thursday
If we did all the things we are capable of, we would literally astound ourselves. 我们如果尽全力去完成我们能做到的事情 ...
- Asp.net中DataTable的排序功能
DataTable里的数据,如果是从数据库中取得的数据,我们可以用order by排序,而从excel表格取得的数据,就需要自己进行操作了. 例如,Dt_Data2是读取Excel表格取到的数据 Da ...
- Alpha冲刺报告(1/12)(麻瓜制造者)
任务分配 这是我们在leangoo上的任务分配: 具体分工如下: 登录界面的编码:邓弘立 肖小强 浏览.检索商品:杜宏庆 汪志彬 待出售的商品: 李佳铭 江郑 数据库建表: 符天愉 刘双玉 图书捐赠模 ...
- 【Ansible 文档】【译文】Ad-Hoc 命令介绍
Introduction To Ad-Hoc Commands Ad-Hoc命令介绍 下面的例子展示了如何使用 /usr/bin/ansible 来运行ad hoc任务. 什么是ad hoc命令? 一 ...
- python string.md
string 包含用于处理文本的常量和类.string模块始于Python的最早版本. 2.0版本中, 许多之前只在模块中实现的函数被转移为string对象的方法. 之后的版本中, 虽然这些函数仍然可 ...
- 支付宝即时到账接口开发 - DEMO讲解
支付宝即时到帐接口 环境要求 PHP5.0以上,且需要开启curl.openssl. 文档地址: https://doc.open.alipay.com/doc2/detail?treeId=62&a ...