日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯(lián)網營銷解決方案
Vue是如何用Rollup打包的?

近期在團隊內組織學習 Rollup 專題,在著重介紹了 Rollup 核心概念和插件的 Hooks 機制后,為了讓小伙伴們能夠深入了解 Rollup 在實際項目中的應用。我們就把目光轉向了優(yōu)秀的開源項目,之后就選擇了尤大的 Vue/Vite/Vue3 項目,接下來本文將先介紹 Rollup 在 Vue 中的應用。

創(chuàng)新互聯(lián)主營阜寧網站建設的網絡公司,主營網站建設方案,App定制開發(fā),阜寧h5微信小程序開發(fā)搭建,阜寧網站營銷推廣歡迎阜寧等地區(qū)企業(yè)咨詢

dev 命令

在 vue-2.6.14 項目根目錄下的 package.json 文件中,我們可以找到 scripts 字段,在該字段內定義了如何構建 Vue 項目的相關腳本。

{
"name": "vue",
"version": "2.6.14",
"sideEffects": false,
"scripts": {
"dev": "rollup -w -c scripts/config.js --environment TARGET:web-full-dev",
"dev:cjs": "rollup -w -c scripts/config.js --environment TARGET:web-runtime-cjs-dev",
...
}

這里我們以 dev 命令為例,來介紹一下與 rollup 相關的配置項:

  • -c:指定 rollup 打包的配置文件;
  • -w:開啟監(jiān)聽模式,當文件發(fā)生變化的時候,會自動打包;
  • --environment:設置環(huán)境變量,設置后可以通過 process.env 對象來獲取已配置的值。

由 dev 命令可知 rollup 的配置文件是 scripts/config.js:

// scripts/config.js
// 省略大部分代碼
if (process.env.TARGET) {
module.exports = genConfig(process.env.TARGET)
} else {
exports.getBuild = genConfig
exports.getAllBuilds = () => Object.keys(builds).map(genConfig)
}

觀察以上代碼可知,當 process.env.TARGET 有值的話,就會根據 TARGET 的值動態(tài)生成打包配置對象。

// scripts/config.js
function genConfig (name) {
const opts = builds[name]
const config = {
input: opts.entry,
external: opts.external,
plugins: [
flow(),
alias(Object.assign({}, aliases, opts.alias))
].concat(opts.plugins || []),
output: {
file: opts.dest,
format: opts.format,
banner: opts.banner,
name: opts.moduleName || 'Vue'
},
onwarn: (msg, warn) => {
if (!/Circular/.test(msg)) {
warn(msg)
}
}
}
// 省略部分代碼
return config
}

在 genConfig 函數內部,會從 builds 對象中獲取當前目標對應的構建配置對象。當目標為 'web-full-dev' 時,它對應的配置對象如下所示:


// scripts/config.js
const builds ={
'web-runtime-cjs-dev': { ... },
'web-runtime-cjs-prod': { ... },
// Runtime+compiler development build (Browser)
'web-full-dev': {
entry: resolve('web/entry-runtime-with-compiler.js'),
dest: resolve('dist/vue.js'),
format: 'umd',
env: 'development',
alias: { he: './entity-decoder' },
banner
},
}

在每個構建配置對象中,會定義 entry(入口文件)、dest (輸出文件)、format(輸出格式)等信息。當獲取構建配置對象后,就根據 rollup 的要求生成對應的配置對象。

需要注意的是,在 Vue 項目的根目錄中是沒有 web 目錄的,該項目的目錄結構如下所示:


├── BACKERS.md
├── LICENSE
├── README.md
├── benchmarks
├── dist
├── examples
├── flow
├── package.json
├── packages
├── scripts
├── src
├── test
├── types
└── yarn.lock

那么 web/entry-runtime-with-compiler.js 入口文件的位置在哪呢?其實是利用了 rollup 的 @rollup/plugin-alias 插件為地址取了個別名。具體的映射規(guī)則被定義在 scripts/alias.js 文件中:

// scripts/alias.js
const path = require('path')
const resolve = p => path.resolve(__dirname, '../', p)

module.exports = {
vue: resolve('src/platforms/web/entry-runtime-with-compiler'),
compiler: resolve('src/compiler'),
core: resolve('src/core'),
shared: resolve('src/shared'),
web: resolve('src/platforms/web'),
weex: resolve('src/platforms/weex'),
server: resolve('src/server'),
sfc: resolve('src/sfc')
}

根據以上的映射規(guī)則,我們可以定位到 web 別名對應的路徑,該路徑對應的文件結構如下:


├── compiler
├── entry-compiler.js
├── entry-runtime-with-compiler.js
├── entry-runtime.js
├── entry-server-basic-renderer.js
├── entry-server-renderer.js
├── runtime
├── server
└── util

到這里結合前面介紹的 builds 對象,相信你也知道了 Vue 是如何打包不同類型的文件,以滿足不同場景的需求,比如含有編譯器和不包含編譯器的版本。分析完 dev 命令的處理流程,下面我來分析 build 命令。

build 命令

同樣,在根目錄下 package.json 的 scripts 字段,我們可以找到 build 命令的定義:

{
"name": "vue",
"version": "2.6.14",
"sideEffects": false,
"scripts": {
"build": "node scripts/build.js",
...
}

當你運行 build 命令時,會使用 node 應用程序執(zhí)行 scripts/build.js 文件:

// scripts/build.js
let builds = require('./config').getAllBuilds()

// filter builds via command line arg
if (process.argv[2]) {
const filters = process.argv[2].split(',')
builds = builds.filter(b => {
return filters.some(f => b.output.file.indexOf(f) > -1
|| b._name.indexOf(f) > -1)
})
} else {
// filter out weex builds by default
builds = builds.filter(b => {
return b.output.file.indexOf('weex') === -1
})
}

build(builds)

在 scripts/build.js 文件中,會先獲取所有的構建目標,然后根據進行過濾操作,最后再調用 build 函數進行構建操作,該函數的處理邏輯也很簡單,就是遍歷構建列表,然后調用 buildEntry 函數執(zhí)行構建操作。

// scripts/build.js
function build (builds) {
let built = 0
const total = builds.length
const next = () => {
buildEntry(builds[built]).then(() => {
built++
if (built < total) {
next()
}
}).catch(logError)
}

next()
}

當 next 函數執(zhí)行時,就會開始調用 buildEntry 函數,在該函數內部就是根據傳入了配置對象調用 rollup.rollup API 進行構建操作:

// scripts/build.js
function buildEntry (config) {
const output = config.output
const { file, banner } = output
const isProd = /(min|prod)\.js$/.test(file)
return rollup.rollup(config)
.then(bundle => bundle.generate(output))
.then(({ output: [{ code }] }) => {
if (isProd) { // 若為正式環(huán)境,則進行壓縮操作
const minified = (banner ? banner + '\n' : '')
+ terser.minify(code, {
toplevel: true,
output: {
ascii_only: true
},
compress: {
pure_funcs: ['makeMap']
}
}).code
return write(file, minified, true)
} else {
return write(file, code)
}
})
}

當打包完成后,下一個環(huán)節(jié)就是生成文件。在 buildEntry 函數中是通過調用 write 函數來生成文件:

// scripts/build.js
const fs = require('fs')

function write (dest, code, zip) {
return new Promise((resolve, reject) => {
function report (extra) {
console.log(blue(path.relative(process.cwd(), dest))
+ ' ' + getSize(code) + (extra || ''))
resolve()
}

fs.writeFile(dest, code, err => {
if (err) return reject(err)
if (zip) {
zlib.gzip(code, (err, zipped) => {
if (err) return reject(err)
report(' (gzipped: ' + getSize(zipped) + ')')
})
} else {
report()
}
})
})
}

write 函數內部是通過 fs.writeFile 函數來生成文件,該函數還支持 zip 參數,用于輸出經過 gzip 壓縮后的大小。現在我們已經分析完了 dev 和 build 命令,最后我們來簡單介紹一下構建過程中所使用的一些核心插件。

rollup 插件

在 package.json 文件中,我們可以看到 Vue2 項目中用到的 rollup 插件:

// package.json
{
"name": "vue",
"version": "2.6.14",
"devDependencies": {
"rollup-plugin-alias": "^1.3.1",
"rollup-plugin-buble": "^0.19.6",
"rollup-plugin-commonjs": "^9.2.0",
"rollup-plugin-flow-no-whitespace": "^1.0.0",
"rollup-plugin-node-resolve": "^4.0.0",
"rollup-plugin-replace": "^2.0.0",
}
}

其中,"rollup-plugin-alias" 插件在前面我們已經知道它的作用了。而其他插件的作用如下:

  • rollup-plugin-buble:該插件使用 buble 轉換 ES2015 代碼,它已經被移到新的倉庫 @rollup/plugin-buble;
  • rollup-plugin-commonjs:該插件用于把 CommonJS 模塊轉換為 ES6 Modules,它已經移到新的倉庫 @rollup/plugin-commonjs;
  • rollup-plugin-flow-no-whitespace:該插件用于移除 flow types 中的空格;
  • rollup-plugin-node-resolve:該插件用于支持使用 node_modules 中第三方模塊,會使用 Node 模塊解析算法來定位模塊。它也被移動到新的倉庫 @rollup/plugin-node-resolve;
  • rollup-plugin-replace:該插件用于在打包時執(zhí)行字符串替換操作,它也被移動到新的倉庫 @rollup/plugin-replace。

除了以上的插件,在實際的項目中,你也可以使用 Rollup 官方倉庫提供的插件,來實現對應的功能,具體如下圖所示(僅包含部分插件):

(來源:https://github.com/rollup/plugins)

總結

本文只是簡單介紹了 Rollup 在 Vue 2 中的應用,很多細節(jié)并沒有展開介紹,感興趣的小伙伴可以自行學習一下。如果遇到問題的話,歡迎跟我一起交流哈。另外,你們也可以自行分析一下在 Vue 3 和 Vite 項目中是如何利用 Rollup 進行打包的。


網站欄目:Vue是如何用Rollup打包的?
轉載注明:http://m.5511xx.com/article/cdjhphi.html