新聞中心
作者:京東零售

目前成都創(chuàng)新互聯(lián)公司已為近1000家的企業(yè)提供了網(wǎng)站建設(shè)、域名、網(wǎng)站空間、網(wǎng)站托管、企業(yè)網(wǎng)站設(shè)計(jì)、衡南網(wǎng)站維護(hù)等服務(wù),公司將堅(jiān)持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。
前言
?在實(shí)際項(xiàng)目開發(fā)中無論 M 端、PC 端,或多或少都有一個(gè) utils 文件目錄去管理項(xiàng)目中用到的一些常用的工具方法,比如:時(shí)間處理、價(jià)格處理、解析url參數(shù)、加載腳本等,其中很多是重復(fù)、基礎(chǔ)、或基于某種業(yè)務(wù)場景的工具,存在項(xiàng)目間冗余的痛點(diǎn)以及工具方法規(guī)范不統(tǒng)一的問題。
?在實(shí)際開發(fā)過程中,經(jīng)常使用一些開源工具庫,如 lodash,以方便、快捷的進(jìn)行項(xiàng)目開發(fā)。但是當(dāng) npm上沒有自己中意或符合自身業(yè)務(wù)的工具時(shí),我們不得不自己動手,此時(shí)擁有自己的、基于業(yè)務(wù)的工具庫就顯得尤為重要。
?我們所熟知的Vue、React等諸多知名前端框架,或公司提供的一些類庫,它們是如何開發(fā)、構(gòu)建、打包出來的,本文將帶領(lǐng)你了解到如何從0到1構(gòu)建基于自身業(yè)務(wù)的前端工具庫。
構(gòu)建工具庫主流方案
1. WEBPACK
? webpack 提供了構(gòu)建和打包不同模塊化規(guī)則的庫,只是需要自己去搭建開發(fā)底層架構(gòu)。
? vue-cli,基于 webpack , vue-cli 腳手架工具可以快速初始化一個(gè) vue 應(yīng)用,它也可以初始化一個(gè)構(gòu)建庫。
2. ROLLUP
? rollup 是一個(gè)專門針對JavaScript模塊打包器,可以將應(yīng)用或庫的小塊代碼編譯成更復(fù)雜的功能代碼。
? Vue、React 等許多流行前端框架的構(gòu)建和打包都能看到 rollup 的身影。
為什么采用 ROLLUP 而不是 WEBPACK
?webpack 主要職能是開發(fā)應(yīng)用,而 rollup 主要針對的就是 js 庫的開發(fā),如果你要開發(fā) js 庫,那 webpack 的繁瑣配置和打包后的文件體積就不太適用了,通過webpack打包構(gòu)建出來的源代碼增加了很多工具函數(shù)以外的模塊依賴代碼。
?rollup 只是把業(yè)務(wù)代碼轉(zhuǎn)碼成目標(biāo) js ,小巧且輕便。rollup對于代碼的Tree-shaking和ES6模塊有著算法優(yōu)勢上的支持,如果只想構(gòu)建一個(gè)簡單的庫,并且是基于ES6開發(fā)的,加上其簡潔的API,rollup得到更多開發(fā)者的青睞。
工具庫底層架構(gòu)設(shè)計(jì)
構(gòu)建工具庫底層架構(gòu)大概需要哪些功能的支持:
架構(gòu)依賴需知
在對底層架構(gòu)設(shè)計(jì)的基礎(chǔ)上,首先需要把用到的依賴庫簡單熟悉一下:
rollup 全家桶
?? rollup(工具庫打包構(gòu)建核心包)
?? rollup-plugin-livereload(rollup 插件,熱更新,方便本地 debugger 開發(fā))
?? rollup-plugin-serve(rollup 插件,本地服務(wù)代理,方便在本地 html 中調(diào)試工具)
?? rollup-plugin-terser(rollup 插件,代碼壓縮混淆)
?? rollup-plugin-visualizer(rollup 插件,可視化并分析 Rollup bundle,以查看模塊占用)
?? @rollup/plugin-babel(rollup 插件,rollup 的 babel 插件,ES6 轉(zhuǎn) ES5)
?? @rollup/plugin-commonjs(rollup 插件,用來將 CommonJS 模塊轉(zhuǎn)換為 ES6,這樣它們就可以包含在 Rollup 包中)
?? @rollup/plugin-json(rollup 插件,它將.json 文件轉(zhuǎn)換為 ES6 模塊)
?? @
rollup/plugin-node-resolve(rollup 插件,它使用節(jié)點(diǎn)解析算法定位模塊,用于在節(jié)點(diǎn)模塊中使用第三方 node_modules 包)
?? @rollup/plugin-typescript(rollup 插件,對 typescript 的支持,將 typescript 進(jìn)行 tsc 轉(zhuǎn)為 js)
typescript 相關(guān)
?? typescript(使用 ts 開發(fā)工具庫)
?? tslib(TypeScript 的運(yùn)行庫,它包含了 TypeScript 所有的幫助函數(shù))
?? @
typescript-eslint/eslint-plugin(TypeScript 的 eslint 插件,約束 ts 書寫規(guī)范)
?? @typescript-eslint/parser(ESLint 解析器,它利用 TypeScript ESTree 來允許 ESLint 檢測 TypeScript 源代碼)
文檔相關(guān)
?? typedoc(TypeScript 項(xiàng)目的文檔生成器)
?? gulp(使用 gulp 構(gòu)建文檔系統(tǒng))
?? gulp-typedoc(Gulp 插件來執(zhí)行 TypeDoc 工具)
?? browser-sync(文檔系統(tǒng)熱更新)
單元測試相關(guān)
?? jest(一款優(yōu)雅、簡潔的 JavaScript 測試框架)
?? @types/jest(Jest 的類型定義)
?? ts-jest(一個(gè)支持源映射的 Jest 轉(zhuǎn)換器,允許您使用 Jest 來測試用 TypeScript 編寫的項(xiàng)目)
?? @babel/preset-typescript(TypeScript 的 Babel 預(yù)設(shè))
其他依賴
?? eslint(代碼規(guī)范約束)
?? @babel/core(@rollup/plugin-babel 依賴的 babel 解析插件)
?? @
babel/plugin-transform-runtime(babel 轉(zhuǎn)譯依賴)
?? @babel/preset-env(babel 轉(zhuǎn)譯依賴)
?? chalk(控制臺字符樣式)
?? rimraf(UNIX 命令 rm -rf 用于 node)
?? cross-env(跨平臺設(shè)置 node 環(huán)境變量)
底層架構(gòu)搭建
1. 初始化項(xiàng)目
新建一個(gè)文件夾 utils-demo,執(zhí)行 npm init,過程會詢問構(gòu)建項(xiàng)目的基本信息,按需填寫即可:
npm init
2. 組織工具庫業(yè)務(wù)開發(fā) SRC 目錄結(jié)構(gòu)
創(chuàng)建工具庫業(yè)務(wù)開發(fā) src 文件目錄,明確怎樣規(guī)劃工具庫包,里面放置的是工具庫開發(fā)需要的業(yè)務(wù)代碼:
3. 安裝項(xiàng)目依賴
要對 typescript 代碼進(jìn)行解析支持需要安裝對 ts 支持的依賴,以及對開發(fā)的工具的一些依賴包:
yarn add typescript tslib rollup rollup-plugin-livereload rollup-plugin-serve rollup-plugin-terser rollup-plugin-visualizer
@rollup/plugin-babel @rollup/plugin-commonjs @rollup/plugin-json @rollup/plugin-node-resolve @rollup/plugin-typescript
@babel/core @babel/plugin-transform-runtime @babel/preset-env rimraf lodash chalk@^4.1.2 -D這里遇到一個(gè)坑,關(guān)于最新 chalk5.0.0 不支持在 nodejs 中 require()導(dǎo)入,所以鎖定包版本 chalk@^4.1.2
要對 typescript 進(jìn)行解析和編譯還需要配置 tsconfig.json,該文件中指定了用來編譯這個(gè)項(xiàng)目的根文件和編譯選項(xiàng),在項(xiàng)目根目錄,使用 tsc --init 命令快速生成 tsconfig.json 文件(前提全局安裝 typescript)
npm i typescript -g
tsc --init初始化 tsconfig 完成之后,根目錄自動生成 tsconfig.json 文件,需要對其進(jìn)行簡單的配置,以適用于 ts 項(xiàng)目,其中具體含義可以參考tsconfig.json官網(wǎng)
4. 組織項(xiàng)目打包構(gòu)建 SCRIPTS 目錄結(jié)構(gòu)
1) 根目錄創(chuàng)建項(xiàng)目打包構(gòu)建 scripts 腳本文件目錄,里面放置的是有關(guān)于項(xiàng)目打包構(gòu)建需要的文件:
生成rollup配置項(xiàng)函數(shù)核心代碼:
const moduleName = camelCase(name) // 當(dāng)format為iife和umd時(shí)必須提供,將作為全局變量掛在window下:window.moduleName=...
const banner = generateBanner() // 包說明文案
// 生成rollup配置文件函數(shù)
const generateConfigs = (options) => {
const { input, outputFile } = options
console.log(chalk.greenBright(`獲取打包入口:${input}`))
const result = []
const pushPlugins = ({ format, plugins, ext }) => {
result.push({
input, // 打包入口文件
external: [], // 如果打包出來的文件有項(xiàng)目依賴,可以在這里配置是否將項(xiàng)目依賴一起打到包里面還是作為外部依賴
// 打包出口文件
output: {
file: `${outputFile}${ext}`, // 出口文件名稱
sourcemap: true, // // 是否生成sourcemap
format, // 打包的模塊化格式
name: moduleName, // 當(dāng)format為iife和umd時(shí)必須提供,將作為全局變量掛在window下:window.moduleName=...
exports: 'named' /** Disable warning for default imports */,
banner, // 打包出來的文件在最頂部的說明文案
globals: {} // 如果external設(shè)置了打包忽略的項(xiàng)目依賴,在此配置,項(xiàng)目依賴的全局變量
},
plugins // rollup插件
})
}
buildType.forEach(({ format, ext }) => {
let plugins = [...defaultPlugins]
// 生產(chǎn)環(huán)境加入包分析以及代碼壓縮
plugins = [
...plugins,
visualizer({
gzipSize: true,
brotliSize: true
}),
terser()
]
pushPlugins({ format, plugins, ext })
})
return result
}2) rollup 在打包構(gòu)建的過程中需要進(jìn)行 babel 的轉(zhuǎn)譯,需要在根目錄添加.babelrc 文件告知 babel:
{
"presets": [
[
"@babel/preset-env"
]
],
"plugins": ["@babel/plugin-transform-runtime"]
}3) 此時(shí)距離打包構(gòu)建工具庫只差一步之遙,配置打包腳本命令,在 package.json 中配置命令:
"scripts": {
"build": "rimraf lib && rollup -c ./scripts/rollup.config.js" // rollup打包
},4) 執(zhí)行 yarn build,根目錄會構(gòu)建出一個(gè) lib 文件夾,里面有打包構(gòu)建的文件,還多了一個(gè) stats.html,這個(gè)是可視化并分析 Rollup bundle,用來查看工具模塊占用空間:
架構(gòu)搭建優(yōu)化
項(xiàng)目搭建到這里,不知機(jī)智的你能否發(fā)現(xiàn)問題:
1) 只要添加了一個(gè)工具,就要在入口文件導(dǎo)出需要打包構(gòu)建的工具,在多人開發(fā)提交代碼的時(shí)候?qū)⒁齺頉_突的產(chǎn)生:
2) 使用工具庫的時(shí)候,按需引用的顆粒度太細(xì)了,不能滿足一些要求顆粒度粗的朋友,比如:
?? 我想使用該包里面 date 相關(guān)工具,要這樣嗎?
import { dateA, dateB, dateC } from "utils-demo"能不能這樣?
import { date } from "utils-demo"
date.dateA()
date.dateB()
date.dateC()?? 在一些使用 script 腳本引入的場景下,就僅僅需要 date 相關(guān)的工具,要這樣嗎?


咨詢
建站咨詢