在上一篇笔记中:Vuex 4源码学习笔记 - 通过单元测试来看工具函数(七)

我们通过单元测试学习了Vuex所用到的工具函数。

今天我们通过Vuex的npm run build,看看能学习到什么

首先我们通过package.json中的scripts可以看到,实际是使用node运行了scripts/build.js文件

"scripts": {//..."build": "node scripts/build.js",//...
}

打开scripts/build.js文件

// fs-extra 是原生fs的替代品。 fs中的所有方法都附加到fs-extra。如果回调未通过,所有fs方法都会返回Promise。
const fs = require('fs-extra')
// chalk 用来在终端内输出带有样式的字符串
const chalk = require('chalk')
// execa 用来在Node.js中运行各种命令
const execa = require('execa')
// Gzip压缩文件
const { gzipSync } = require('zlib')
// Brotli压缩文件算法
const { compress } = require('brotli')const files = ['dist/vuex.esm-browser.js','dist/vuex.esm-browser.prod.js','dist/vuex.esm-bundler.js','dist/vuex.global.js','dist/vuex.global.prod.js','dist/vuex.cjs.js'
]async function run() {await Promise.all([build(), copy()])checkAllSizes()
}async function build() {await execa('rollup', ['-c', 'rollup.config.js'], { stdio: 'inherit' })
}async function copy() {await fs.copy('src/index.mjs', 'dist/vuex.mjs')}function checkAllSizes() {console.log()files.map((f) => checkSize(f))console.log()
}function checkSize(file) {const f = fs.readFileSync(file)const minSize = (f.length / 1024).toFixed(2) + 'kb'const gzipped = gzipSync(f)const gzippedSize = (gzipped.length / 1024).toFixed(2) + 'kb'const compressed = compress(f)const compressedSize = (compressed.length / 1024).toFixed(2) + 'kb'console.log(`${chalk.gray(chalk.bold(file))} size:${minSize} / gzip:${gzippedSize} / brotli:${compressedSize}`)
}run()

这个文件主要依赖的NPM包有:

  • fs-extra:fs-extra 是原生fs的替代品。 fs中的所有方法都附加到fs-extra。如果回调未通过,所有fs方法都会返回Promise。
  • chalk:用来在终端内输出带有样式的字符串
  • execa:用来在Node.js中运行各种命令
  • zlib:Gzip压缩文件
  • brotli:Brotli压缩文件算法

这个文件主要做了下面三件事情:

  • build()函数用来使用rollup来进行打包
  • copy()函数用来将src/index.mjs文件拷贝到dist/vuex.mjs
  • checkAllSizes()函数用来检查每个打包后的文件的大小

接下来就是重要的使用rollup进行将源代码进行打包,我们来查看rollup配置文件rollup.config.js

import buble from '@rollup/plugin-buble'
import replace from '@rollup/plugin-replace'
import resolve from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
import { terser } from 'rollup-plugin-terser'
import pkg from './package.json'const banner = `/*!* vuex v${pkg.version}* (c) ${new Date().getFullYear()} Evan You* @license MIT*/`const configs = [// 浏览器引入ES Module的开发版本{ input: 'src/index.js', file: 'dist/vuex.esm-browser.js', format: 'es', browser: true, env: 'development' },// 浏览器引入ES Module的生产版本{ input: 'src/index.js', file: 'dist/vuex.esm-browser.prod.js', format: 'es', browser: true, env: 'production' },// ES模块方式引入 import Vuex from 'vuex'{ input: 'src/index.js', file: 'dist/vuex.esm-bundler.js', format: 'es', env: 'development' },// 浏览器CDN方式引入的开发版本{ input: 'src/index.cjs.js', file: 'dist/vuex.global.js', format: 'iife', env: 'development' },// 浏览器CDN方式引入的生产版本{ input: 'src/index.cjs.js', file: 'dist/vuex.global.prod.js', format: 'iife', minify: true, env: 'production' },// commonjs模块方式引入 require('vuex'){ input: 'src/index.cjs.js', file: 'dist/vuex.cjs.js', format: 'cjs', env: 'development' }
]function createEntries () {return configs.map((c) => createEntry(c))
}function createEntry (config) {const isGlobalBuild = config.format === 'iife'const isBundlerBuild = config.format !== 'iife' && !config.browserconst isBundlerESMBuild = config.format === 'es' && !config.browserconst c = {external: ['vue'], // 要排除的模块ID,排除vue依赖input: config.input, // 入口文件地址plugins: [], // 所有插件output: {banner, // 在打包后文件顶部插入的代码file: config.file, // 输出文件地址format: config.format, // 输出类型(amd、cjs、es、iife、umd、system)globals: { // 告诉Rollup,Vue 是外部依赖vue: 'Vue'}/*var MyBundle = (function (Vue) {// code goes here}(Vue));*/},// 拦截警告消息的函数onwarn: (msg, warn) => {if (!/Circular/.test(msg)) {warn(msg)}}}if (isGlobalBuild) {// 对于导出的iife/umd包是必需的,它代表包的全局变量名称。c.output.name = c.output.name || 'Vuex'}if (!isGlobalBuild) {// 排除@vue/devtools-api依赖c.external.push('@vue/devtools-api')}// Rollup插件,在打包时替换文件中的目标字符串。c.plugins.push(replace({preventAssignment: true,__VERSION__: pkg.version,__DEV__: isBundlerBuild? `(process.env.NODE_ENV !== 'production')`: config.env !== 'production',__VUE_PROD_DEVTOOLS__: isBundlerESMBuild? '__VUE_PROD_DEVTOOLS__': 'false'}))// 一个使用buble编译器转换ES2015+代码的Rollup插件。if (config.transpile !== false) {c.plugins.push(buble())}// 一个使用Node解析算法定位模块的Rollup插件,用于在node_modules中使用第三方模块c.plugins.push(resolve())// 一个Rollup插件,用于将CommonJS模块转换为ES6c.plugins.push(commonjs())// Rollup插件,用于缩小生成的es包。if (config.minify) {c.plugins.push(terser({ module: config.format === 'es' }))}return c
}export default createEntries()

使用Rollup打包主要用到了下面的一些插件功能:

  • @rollup/plugin-buble:使用buble编译器转换ES2015+代码的Rollup插件。
  • @rollup/plugin-replace:在打包时替换文件中的目标字符串。
  • @rollup/plugin-node-resolve:使用Node解析算法定位模块的Rollup插件,用于在node_modules中使用第三方模块
  • @rollup/plugin-commonjs:用于将CommonJS模块转换为ES6
  • rollup-plugin-terser:用于缩小生成的es包。

打包的目标产物有以下六个:

  • dist/vuex.esm-browser.js:用于通过原生 ES 模块导入使用 (在浏览器中通过 <script type="module"> 来使用)。开发版本。

  • dist/vuex.esm-browser.prod.js:同上,作为生产版本。

  • dist/vuex.esm-bundler.js:ES模块方式引入 import Vuex from 'vuex',用于 webpackrollupparcel 等构建工具,不提供压缩版本 (打包后与其余代码一起压缩)。

  • dist/vuex.global.js:浏览器CDN方式引入的开发版本

  • dist/vuex.global.prod.js:浏览器CDN方式引入的生产版本

  • dist/vuex.cjs.js:commonjs模块方式引入 const Vuex = require('vuex'),通过 require() 在 Node.js 服务器端渲染使用。

每个产物对应着不同的使用平台。

一起学习更多前端知识,微信搜索【小帅的编程笔记】,每天更新

Vuex 4源码学习笔记 - 通过build我们能学习到什么(八)相关推荐

  1. libreCAD源码阅读笔记2

    libreCAD源码阅读笔记2 1. 前言 继续学习QC_MDIWindow类.QG_ActionHandler类相关代码 2. QC_MDIWindow类 QC_MDIWindow类继承QT QMd ...

  2. Vuex 4源码学习笔记 - 通过Vuex源码学习E2E测试(十一)

    在上一篇笔记中:Vuex 4源码学习笔记 - 做好changelog更新日志很重要(十) 我们学到了通过conventional-changelog来生成项目的Changelog更新日志,通过更新日志 ...

  3. Vuex 4源码学习笔记 - 通过dispatch一步步来掌握Vuex整个数据流(五)

    在上一篇笔记中:Vuex 4源码学习笔记 - Store 构造函数都干了什么(四) 我们通过查看Store 构造函数的源代码可以看到主要做了三件事情: 初始化一些内部变量以外 执行installMod ...

  4. React深入学习与源码解析笔记

    ***当前阶段的笔记 *** 「面向实习生阶段」https://www.aliyundrive.com/s/VTME123M4T9 提取码: 8s6v 点击链接保存,或者复制本段内容,打开「阿里云盘」 ...

  5. Android Dialer,Mms,Contacts源码修改笔记,移动端混合开发经验

    ②在AndroidManifest.xml中修改相应Activity的theme <activity android:name=".HomeActivity" android ...

  6. libreCAD源码阅读笔记1

    libreCAD源码阅读笔记1 一 前言: 正如官网(https://www.librecad.org)所说,libreCAD是一个开源的CAD制图软件,可以运行在Windows.Apple.Linu ...

  7. libreCAD源码阅读笔记4

    libreCAD源码阅读笔记4 前言 总的来说,程序主窗口QC_ApplicationWindow使用QMdiArea作为多文档主界面,每个文档QC_MDIWindow使用RS_Document作为数 ...

  8. 源码解析:Spring源码解析笔记(五)接口设计总览

    本文由colodoo(纸伞)整理 QQ 425343603 Java学习交流群(717726984) Spring解析笔记 启动过程部分已经完成,对启动过程源码有兴趣的朋友可以作为参考文章. 源码解析 ...

  9. HashMap源码阅读笔记

    HashMap是Java编程中常用的集合框架之一. 利用idea得到的类的继承关系图可以发现,HashMap继承了抽象类AbstractMap,并实现了Map接口(对于Serializable和Clo ...

  10. dgl源码阅读笔记(3)——DeepWalk

    dgl源码阅读笔记(3)--DeepWalk 图神经网络开源库dgl阅读笔记 文章目录 dgl源码阅读笔记(3)--DeepWalk 图神经网络开源库dgl阅读笔记 @[TOC](文章目录) 前言 一 ...

最新文章

  1. 基于Python的验证码识别技术
  2. The Third Revolution in Sequencing Technology 测序技术的第三次革命
  3. 小白的python之路11/3总结
  4. [BZOJ1724][Usaco2006 Nov]Fence Repair 切割木板
  5. 【MATLAB】二维绘图 ( 绘制二维图像 | 设置图像样式 )
  6. secureCRT 实现windows和linux文件互传
  7. Gmail技巧之无限别名
  8. android应用开发全程实录-实现甩动拨打和挂断电话
  9. MySQL学习笔记之五:存储引擎和查询缓存
  10. JDBC(Java语言连接数据库)
  11. 利用数据库来填充UltraWebTree
  12. 一个简单的crontab
  13. 安装grunt-browser-sync时报错:“未能加载Visual C++ 组件 “VCBuild.exe”
  14. Kotlin入门(13)类成员的众生相
  15. 详解python 字符串
  16. 数据结构c语言版堆排序,【数据结构】堆排序(C++实现)
  17. 【图像配准】基于matlab GUI互相关图像配准【含Matlab源码 853期】
  18. ArcMap进行标记符号制作
  19. 2012“第四届云计算中国峰会”倒计时
  20. 5大可以赚钱的视频平台,及收益渠道!

热门文章

  1. C10H16IN (PhBAI) 苯丁基碘化铵
  2. cheby1设计低通高通滤波器
  3. 动态数据模型分析与应用
  4. Hadoop MapReduce性能调优
  5. 钱是比武器更厉害的武器——人民币的升值与中美
  6. 感性认识神经网络的反向传播
  7. TLS1.3中文版上(RFC8446)(注:本文有错误但无法修改,正确的见后来文章)
  8. 商业周刊:移动广告为何步履维艰
  9. ecshop上传视频_ecshop视频列表,视频分类,视频关联商品导购
  10. Qt学生和教师的教育许可证