在上一篇笔记中:Vuex 4源码学习笔记 - 通过单元测试来看工具函数(七)
我们通过单元测试学习了Vuex所用到的工具函数。
今天我们通过Vuex的npm run build ,看看能学习到什么
首先我们通过package.json中的scripts可以看到,实际是使用node运行了scripts/build.js 文件
"scripts": {
"build": "node scripts/build.js",
}
打开scripts/build.js 文件
const fs = require('fs-extra')
const chalk = require('chalk')
const execa = require('execa')
const { gzipSync } = require('zlib')
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 = [
{ input: 'src/index.js', file: 'dist/vuex.esm-browser.js', format: 'es', browser: true, env: 'development' },
{ input: 'src/index.js', file: 'dist/vuex.esm-browser.prod.js', format: 'es', browser: true, env: 'production' },
{ input: 'src/index.js', file: 'dist/vuex.esm-bundler.js', format: 'es', env: 'development' },
{ input: 'src/index.cjs.js', file: 'dist/vuex.global.js', format: 'iife', env: 'development' },
{ input: 'src/index.cjs.js', file: 'dist/vuex.global.prod.js', format: 'iife', minify: true, env: 'production' },
{ 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.browser
const isBundlerESMBuild = config.format === 'es' && !config.browser
const c = {
external: ['vue'],
input: config.input,
plugins: [],
output: {
banner,
file: config.file,
format: config.format,
globals: {
vue: 'Vue'
}
},
onwarn: (msg, warn) => {
if (!/Circular/.test(msg)) {
warn(msg)
}
}
}
if (isGlobalBuild) {
c.output.name = c.output.name || 'Vuex'
}
if (!isGlobalBuild) {
c.external.push('@vue/devtools-api')
}
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'
}))
if (config.transpile !== false) {
c.plugins.push(buble())
}
c.plugins.push(resolve())
c.plugins.push(commonjs())
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模块转换为ES6rollup-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' ,用于 webpack ,rollup 和 parcel 等构建工具,不提供压缩版本 (打包后与其余代码一起压缩)。 -
dist/vuex.global.js :浏览器CDN方式引入的开发版本 -
dist/vuex.global.prod.js :浏览器CDN方式引入的生产版本 -
dist/vuex.cjs.js :commonjs模块方式引入 const Vuex = require('vuex') ,通过 require() 在 Node.js 服务器端渲染使用。
每个产物对应着不同的使用平台。
一起学习更多前端知识,微信搜索【小帅的编程笔记】,每天更新
|