Vue3中使用pnpm搭建monorepo開發(fā)環(huán)境_第1頁
Vue3中使用pnpm搭建monorepo開發(fā)環(huán)境_第2頁
Vue3中使用pnpm搭建monorepo開發(fā)環(huán)境_第3頁
Vue3中使用pnpm搭建monorepo開發(fā)環(huán)境_第4頁
Vue3中使用pnpm搭建monorepo開發(fā)環(huán)境_第5頁
已閱讀5頁,還剩7頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

第Vue3中使用pnpm搭建monorepo開發(fā)環(huán)境目錄前言Pnpm和Monorepo搭建開發(fā)環(huán)境創(chuàng)建項(xiàng)目配置monorepo安裝依賴初始化Typescript準(zhǔn)備兩個(gè)模塊sharedreactivity編寫構(gòu)建腳本完成第一次調(diào)試小結(jié)

前言

Vue3源碼閱讀系列,計(jì)劃從環(huán)境搭建開始,將Vue3的響應(yīng)式模塊,運(yùn)行時(shí)模塊和編譯器模塊,以及狀態(tài)庫Pinia、路由庫Vue-Router的核心原理做一個(gè)梳理。這大概是一個(gè)漫長的過程。祝自己不要爛尾,祝大家有所收獲。

Pnpm和Monorepo

Pnpm是新一代的nodejs包管理工具。第一個(gè)P意為Performance,代表著更佳的性能。

它的主要優(yōu)點(diǎn)有兩個(gè),一是采用了hard-link機(jī)制,避免了包的重復(fù)安裝,節(jié)省了空間,同時(shí)能提高項(xiàng)目依賴的安裝速度。二是對monorepo的支持非常友好,只需要一條配置就能實(shí)現(xiàn)。

Monorepo是一種新的倉庫管理方式。過去的項(xiàng)目,大多采用一個(gè)倉庫維護(hù)一個(gè)項(xiàng)目的方案。對于一個(gè)龐大復(fù)雜的項(xiàng)目,哪怕只進(jìn)行一處小小的修改,影響的也是整體。而采用monorepo的形式,我們可以在一個(gè)倉庫中管理多個(gè)包。每個(gè)包都可以單獨(dú)發(fā)布和使用,就好像是一個(gè)倉庫中又有若干個(gè)小倉庫。

Vue3源碼采用monorepo方式進(jìn)行管理,將眾多模塊拆分到packages目錄中。

這帶來的最直觀的好處,就是方便管理和維護(hù)。而且,它不像Vue2那樣將源碼整體打包對外暴露。Vue3的這種組織形式,方便的實(shí)現(xiàn)了Tree-shaking,需要哪個(gè)功能就引入對應(yīng)的模塊,能大大減少打包后項(xiàng)目的體積。

搭建開發(fā)環(huán)境

創(chuàng)建項(xiàng)目

首先全局安裝pnpm:

npminstall-gpnpm

新建一個(gè)目錄并進(jìn)行初始化:

mkdirvue3-learn

cdvue3-learn

pnpminit

mkdirpackages

配置monorepo

在項(xiàng)目根目錄下新建pnpm-workspace.yaml文件:

packages:

-'packages/*'

意思是,將packages目錄下所有的目錄都作為單獨(dú)的包進(jìn)行管理。

通過這樣一個(gè)簡單的配置,Monorepo開發(fā)環(huán)境搭建好了。

如果大家之前接觸過lerna+yarnworkspace的方案,就會(huì)深有體會(huì),使用pnpm的確方便。Vue3,ElementPlus以前采用的方案就是前者,現(xiàn)在都已經(jīng)改用后者了。

安裝依賴

如果你使用過Vite,就一定體驗(yàn)過它的快。因?yàn)閂ite內(nèi)置了esbuild作為開發(fā)階段的構(gòu)建工具。esbuild的特點(diǎn)就是快。

Vue3采用了和vite一致的選擇,開發(fā)階段使用esbuild作為構(gòu)建工具,在生產(chǎn)階段采用rollup進(jìn)行打包。

我們先安裝一些依賴:

#源碼采用typescript編寫

pnpmadd-D-wtypescript

#構(gòu)建工具,命令行參數(shù)解析工具

pnpmadd-D-wesbuildrolluprollup-plugin-typescript2@rollup/plugin-json@rollup/plugin-node-resolve@rollup/plugin-commonjsminimistexeca

說明:

-D:作為開發(fā)依賴安裝

-w:monorepo環(huán)境默認(rèn)會(huì)認(rèn)為應(yīng)該將依賴安裝到具體的package中。使用-w參數(shù),告訴pnpm將依賴安裝到workspace-root,也就是項(xiàng)目的根目錄。

依賴說明:

依賴描述typescript項(xiàng)目使用typescript進(jìn)行開發(fā)esbuild開發(fā)階段的構(gòu)建工具rollup生產(chǎn)階段的構(gòu)建工具rollup-plugin-typescript2rollup編譯ts的插件@rollup/plugin-jsonrollup默認(rèn)采用esm方式解析模塊,該插件將json解析為esm供rollup處理@rollup/plugin-node-resolverollup默認(rèn)采用esm方式解析模塊,該插件可以解析安裝在node_modules下的第三方模塊@rollup/plugin-commonjs將commonjs模塊轉(zhuǎn)化為esm模塊minimist解析命令行參數(shù)execa生產(chǎn)階段開啟子進(jìn)程

初始化Typescript

pnpmtsc--init

pnpm的使用基本和npm一致。這里的用法就相當(dāng)于npm中的npx:

npxtsc--init

意思是,去node_modules下的.bin目錄中找到tsc命令,并執(zhí)行它。

執(zhí)行完該命令,會(huì)在項(xiàng)目根目錄生成一個(gè)tsconfig.json文件,進(jìn)行一些配置:

{

"compilerOptions":{

"outDir":"dist",//輸出的目錄

"sourceMap":true,//開啟sourcemap

"target":"es2016",//轉(zhuǎn)譯的目標(biāo)語法

"module":"esnext",//模塊格式

"moduleResolution":"node",//模塊解析方式

"strict":false,//關(guān)閉嚴(yán)格模式,就能使用any了

"resolveJsonModule":true,//解析json模塊

"esModuleInterop":true,//允許通過es6語法引入commonjs模塊

"jsx":"preserve",//jsx不轉(zhuǎn)義

"lib":["esnext","dom"],//支持的類庫esnext及dom

"baseUrl":".",//當(dāng)前目錄,即項(xiàng)目根目錄作為基礎(chǔ)目錄

"paths":{//路徑別名配置

"@my-vue/*":["packages/*/src"]//當(dāng)引入@my-vue/時(shí),去packages/*/src中找

準(zhǔn)備兩個(gè)模塊

我們先在packages目錄下新建兩個(gè)模塊,分別是reactivity響應(yīng)式模塊和shared工具庫模塊。然后編寫構(gòu)建腳本進(jìn)行第一次的開發(fā)調(diào)試。

shared

在packages下新建shared目錄,并初始化:

pnpminit

然后修改package.json:

{

"name":"@my-vue/shared",

"version":"1.0.0",

"description":"@my-vue/shared",

"main":"dist/shared.cjs.js",

"module":"dist/shared.esm-bundler.js"

注意name字段的值,我們使用了一個(gè)@scope作用域,它相當(dāng)于npm包的命名空間,可以使項(xiàng)目結(jié)構(gòu)更加清晰,也能減少包的重名。

編寫該模塊的入口文件:

//src/index.ts

*判斷對象

exportconstisObject=(value)={

returntypeofvalue==='object'value!==null

*判斷函數(shù)

exportconstisFunction=(value)={

returntypeofvalue==='function'

*判斷字符串

exportconstisString=(value)={

returntypeofvalue==='string'

*判斷數(shù)字

exportconstisNumber=(value)={

returntypeofvalue==='number'

*判斷數(shù)組

exportconstisArray=Array.isArray

reactivity

在packages下新建reactivity目錄,并初始化:

pnpminit

然后修改package.json:

{

"name":"@my-vue/reactivity",

"version":"1.0.0",

"description":"@my-vue/reactivity",

"main":"dist/reactivity.cjs.js",

"module":"dist/reactivity.esm-bundler.js",

"buildOptions":{

"name":"VueReactivity"

在瀏覽器中以IIFE格式使用響應(yīng)式模塊時(shí),需要給模塊指定一個(gè)全局變量名字,通過buildO進(jìn)行指定,將來打包時(shí)會(huì)作為配置使用。

main指定的文件支持commonjs規(guī)范進(jìn)行導(dǎo)入,也就是說在nodejs環(huán)境中,通過require方法導(dǎo)入該模塊時(shí),會(huì)導(dǎo)入main指定的文件。

同理,module指定的是使用ESModule規(guī)范導(dǎo)入模塊時(shí)的入口文件。

編寫該模塊的入口文件:

//src/index.ts

import{isObject}from'@my-vue/shared'

constobj={name:'Vue3'}

console.log(isObject(obj))

在reactivity包中用到了另一個(gè)包shared,需要安裝才能使用:

pnpmadd@my-vue/shared@workspace--filter@my-vue/reactivity

意思是,將本地workspace內(nèi)的@my-vue/shared包,安裝到@my-vue/reactivity包中去。

此時(shí),查看reactivity包的依賴信息:

"dependencies":{

"@my-vue/shared":"workspace:^1.0.0"

編寫構(gòu)建腳本

在根目錄下新建scripts目錄,存放項(xiàng)目構(gòu)建的腳本。

新建dev.js,作為開發(fā)階段的構(gòu)建腳本。

//scripts/dev.js

//使用minimist解析命令行參數(shù)

constargs=require('minimist')(process.argv.slice(2))

constpath=require('path')

//使用esbuild作為構(gòu)建工具

const{build}=require('esbuild')

//需要打包的模塊。默認(rèn)打包reactivity模塊

consttarget=args._[0]||'reactivity'

//打包的格式。默認(rèn)為global,即打包成IIFE格式,在瀏覽器中使用

constformat=args.f||'global'

//打包的入口文件。每個(gè)模塊的src/index.ts作為該模塊的入口文件

constentry=path.resolve(__dirname,`../packages/${target}/src/index.ts`)

//打包文件的輸出格式

constoutputFormat=format.startsWith('global')'iife':format==='cjs''cjs':'esm'

//文件輸出路徑。輸出到模塊目錄下的dist目錄下,并以各自的模塊規(guī)范為后綴名作為區(qū)分

constoutfile=path.resolve(__dirname,`../packages/${target}/dist/${target}.${format}.js`)

//讀取模塊的package.json,它包含了一些打包時(shí)需要用到的配置信息

constpkg=require(path.resolve(__dirname,`../packages/${target}/package.json`))

//buildO是模塊打包為IIFE格式時(shí)的全局變量名字

constpgkGlobalName=pkg.buildO

console.log('模塊信息:\n',entry,'\n',format,'\n',outputFormat,'\n',outfile)

//使用esbuild打包

build({

//打包入口文件,是一個(gè)數(shù)組或者對象

entryPoints:[entry],

//輸入文件路徑

outfile,

//將依賴的文件遞歸的打包到一個(gè)文件中,默認(rèn)不會(huì)進(jìn)行打包

bundle:true,

//開啟sourceMap

sourcemap:true,

//打包文件的輸出格式,值有三種:iife、cjs和esm

format:outputFormat,

//如果輸出格式為IIFE,需要為其指定一個(gè)全局變量名字

globalName:pgkGlobalName,

//默認(rèn)情況下,esbuild構(gòu)建會(huì)生成用于瀏覽器的代碼。如果打包的文件是在node環(huán)境運(yùn)行,需要將平臺(tái)設(shè)置為node

platform:format==='cjs''node':'browser',

//監(jiān)聽文件變化,進(jìn)行重新構(gòu)建

watch:{

onRebuild(error,result){

if(error){

console.error('build失敗:',error)

}else{

console.log('build成功:',result)

}).then(()={

console.log('watching...')

使用該腳本,會(huì)使用esbuild對packages下的包進(jìn)行構(gòu)建,打包的結(jié)果放到各個(gè)包的dist目錄下。

在開發(fā)階段,我們默認(rèn)打包成IIFE格式,方便在瀏覽器中使用html文件進(jìn)行測試。在生產(chǎn)階段,會(huì)分別打包成CommonJS,ESModule和IIFE的格式。

完成第一次調(diào)試

給項(xiàng)目增加一條scripts命令:

//package.json

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論