




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
第使用typescript+webpack構(gòu)建一個js庫的示例詳解目錄入口文件tsconfig配置webpack配置文件webpack入口文件配置webpack為typescript和less文件配置各自的loaderwebpack的output配置運行webpack進行打包測試驗證輸出esm模塊已經(jīng)輸出了umd格式的js了,為什么還要輸出esm模塊----TreeShaking用tsc輸出esm和類型聲明文件package.json中添加exports配置聲明模塊導出路徑完善package.json文件用api-extractor提取出干凈的.d.ts配置使用APIextractor更新package.json用@internal標注只希望在內(nèi)部使用的class小結(jié)記錄使用typescript配合webpack打包一個javascriptlibrary的配置過程.
目標是構(gòu)建一個可以同時支持CommonJs,esm,amd這個幾個js模塊系統(tǒng)的javascript庫,然后還有一個單獨打包出一個css的樣式文件的需求.
為此以構(gòu)建一個名為loaf的javascript庫為例;首先新建項目文件目錄loaf,并進入此文件目錄執(zhí)行npminit命令,然后按照控制臺的提示輸入對應(yīng)的信息,完成后就會在loaf目錄下得到一個package.json文件
然后使用npmi命令安裝所需的依賴
npmi-Dwebpackwebpack-clitypescriptbabel-loader@babel/core@babel/preset-env@babel/preset-typescriptts-node@types/node@types/webpackmini-css-extract-plugincss-minimizer-webpack-pluginlessless-loaderterser-webpack-plugin
依賴說明
webpackwebpack-cli:webpack打包工具和webpack命令行接口typescript:用于支持typescript語言babel-loader@babel/core@babel/preset-env@babel/preset-typescript:babel相關(guān)的東西,主要是需要babel-loader將編寫的typescript代碼轉(zhuǎn)譯成es5或es6已獲得更好的瀏覽器兼容性ts-node@types/node@types/webpack:安裝這幾個包是為了能用typescript編寫webpack配置文件(webpack.config.ts)mini-css-extract-pluginlessless-loader:編譯提取less文件到單獨的css文件的相關(guān)依賴css-minimizer-webpack-pluginterser-webpack-plugin:用于最小化js和css文件尺寸的webpack插件
入口文件
通常使用index.ts作為入口,并將其放到src目錄下,由于有輸出樣式文件的需求,所以還要新建styles/index.less
mkdirsrctouchsrc/index.ts
mkdirsrc/stylestouchsrc/styles/index.less
tsconfig配置
新建tsconfig.json文件
touchtsconfig.json
填入以下配置(部分選項配有注釋):
{
"compilerOptions":{
"outDir":"dist/lib",
"sourceMap":false,
"noImplicitAny":true,
"module":"commonjs",
//開啟這個選項,可以讓你直接通過`import`的方式來引用commonjs模塊
//這樣你的代碼庫中就可以統(tǒng)一的使用import導入依賴了,而不需要另外再使用require導入commonjs模塊
"esModuleInterop":true,
//是否允許合成默認導入
//開啟后,依賴的模塊如果沒有導出默認的模塊
//那么typescript會幫你給該模塊自動合成一個默認導出讓你可以通過默認導入的方式引用該模塊
"allowSyntheticDefaultImports":true,
//是否生成`.d.ts`的類型聲明文件
"declaration":true,
//輸出的目標js版本,這里用es6,然后配和babel進行轉(zhuǎn)譯才以獲得良好的瀏覽器兼容
"target":"es6",
"allowJs":true,
"moduleResolution":"node",
"lib":["es2015","dom"],
"declarationMap":true,
//啟用嚴格的null檢查
"strictNullChecks":true,
//啟用嚴格的屬性初始化檢查
//啟用后類屬性必須顯示標注為可空或賦一個非空的初始值
"strictPropertyInitialization":true
"exclude":["node_modules"],
"include":["src/**/*"]
}
webpack配置文件
創(chuàng)建webpack.config.ts
touchwebpack.config.ts
webpack.config.ts
importpathfrom"path";
import{Configuration,Entry}from"webpack";
importMiniCssExtractPluginfrom'mini-css-extract-plugin';
importCssMinimizerfrom'css-minimizer-webpack-plugin';
importTerserPluginfrom'terser-webpack-plugin'
constisProd=process.env.NODE_ENV==='production';
*這里用到了webpack的[Multiplefiletypesperentry](/guides/entry-advanced/)特性
*注意`.less`入口文件必須放在`.ts`文件前*/
constentryFiles:string[]=['./src/styles/index.less','./src/index.ts'];
constentry:Entry={
index:entryFiles,
'index.min':entryFiles,
constconfig:Configuration={
entry,
optimization:{
minimize:true,
minimizer:[
newTerserPlugin({test:/.min.js$/}),
newCssMinimizer({
test:/.min.css$/,
module:{
rules:[
test:/.ts$/,
loader:'babel-loader',
exclude:/node_modules/,
options:{
presets:['@babel/env','@babel/typescript'],
test:/.less$/,
use:[
isProdMiniCssExtractPlugin.loader:'style-loader',
loader:'css-loader',
'postcss-loader',
'less-loader',
output:{
path:path.resolve(__dirname,'dist/umd'),
library:{
type:'umd',
name:{
amd:'loaf',
commonjs:'loaf',
root:'loaf',
resolve:{
extensions:['.ts','.less'],
devtool:'source-map',
plugins:[
newMiniCssExtractPlugin({
filename:'[name].css',
exportdefaultconfig;
webpack入口文件配置
...
constisProd=process.env.NODE_ENV==='production';
*這里用到了webpack的[Multiplefiletypesperentry](/guides/entry-advanced/)特性
*注意`.less`入口文件必須放在`.ts`文件前*/
constentryFiles:string[]=['./src/styles/index.less','./src/index.ts'];
constentry:Entry={
index:entryFiles,
'index.min':entryFiles,
constconfig:Configuration={
entry,
...
在上面的webpack.config.json中,我們配置了兩個入口分別是index和index.min,不難看出,多出的一個index.min入口是為了經(jīng)過壓縮后js和css文件,在生產(chǎn)環(huán)境使用一般都會使用.min.js結(jié)尾的文件以減少網(wǎng)絡(luò)傳輸時的尺寸;實現(xiàn)這個還需要結(jié)合optimization相關(guān)配置,如下:
optimization:{
minimize:true,
minimizer:[
newTerserPlugin({test:/.min.js$/}),
newCssMinimizer({
test:/.min.css$/,
},
另外,index和index.min的值都是相同的entryFiles對象,這個對象是一個字符串數(shù)組,里面放的就是我們的入口文件相對路徑,這里一定要注意把./src/styles/index.less置于./src/index.ts之前。
webpack為typescript和less文件配置各自的loader
配置完入口后,就需要為typescript和less代碼配置各自的loader
module:{
rules:[
test:/.ts$/,
loader:'babel-loader',
exclude:/node_modules/,
options:{
presets:['@babel/env','@babel/typescript'],
test:/.less$/,
use:[
isProdMiniCssExtractPlugin.loader:'style-loader',
loader:'css-loader',
'postcss-loader',
'less-loader',
},
mini-css-extract-pluginlessless-loader:編譯提取less文件到單獨的css文件的相關(guān)依賴
上面的配置為.ts結(jié)尾的文件配置了babel-loader;為.less結(jié)尾的文件配置一串loader,使用了use,use中的loader的執(zhí)行順序是從后往前的,上面less的配置就是告訴webpack遇到less文件時,一次用less-loader-postcss-loader-css-loader-生產(chǎn)環(huán)境用MiniCssExtractPlugin.loader()否則用style-loader;
MiniCssExtractPlugin.loader使用前要先在plugins進行初始化
...
constconfig={
plugins:[
newMiniCssExtractPlugin({
filename:'[name].css',
...
webpack的output配置
...
constconfig={
output:{
path:path.resolve(__dirname,'dist/umd'),
library:{
type:'umd',
name:{
amd:'loaf',
commonjs:'loaf',
root:'loaf',
...
這里配置webpack以umd的方式輸出到相對目錄dist/umd目錄中,umd是UniversalModuleDefinition(通用模塊定義)的縮寫,umd格式輸出library允許用戶通過commonjs,AMD,scriptsrc=...的方式對library進行引用可以為不同的模塊系統(tǒng)配置不同的導出模塊名供客戶端來進行引用;由于這里的導出模塊名都是loaf,所以也可以直接設(shè)置成loaf.
運行webpack進行打包
現(xiàn)在回到最開始通過npminit生成的package.json文件,在修改其內(nèi)容如下
{
"name":"loaf",
"version":"1.0.0",
"description":"Ademoshowshowtocreatebuildajavascriptlibrarywithwebpacktypescript",
"main":"index.js",
"scripts":{
"build:umd":"webpack-cwebpack.config.ts--node-envproduction--envNODE_ENV=production",
"test":"npmruntest"
"keywords":[
"demo"
"author":"laggage",
"license":"MIT",
"devDependencies":{
"@babel/core":"^7.18.6",
"@babel/preset-env":"^7.18.6",
"@babel/preset-typescript":"^7.18.6",
"@types/node":"^18.0.0",
"@types/webpack":"^5.28.0",
"babel-loader":"^8.2.5",
"css-loader":"^6.7.1",
"css-minimizer-webpack-plugin":"^4.0.0",
"less":"^4.1.3",
"less-loader":"^11.0.0",
"mini-css-extract-plugin":"^2.6.1",
"postcss-loader":"^7.0.0",
"style-loader":"^3.3.1",
"terser-webpack-plugin":"^5.3.3",
"ts-node":"^10.8.2",
"typescript":"^4.7.4",
"webpack":"^5.73.0",
"webpack-cli":"^4.10.0"
}
新增了一個腳本命令build:umd:webpack-cwebpack.config.ts--node-envproduction--envNODE_ENV=production,然后命令行到項目目錄下執(zhí)行npmrunbuild:umd,不出意外應(yīng)該就構(gòu)建成功了,此時生成的dist目錄結(jié)構(gòu)如下
dist
└──umd
├──index.css
├──index.js
├──index.js.map
├──index.min.css
├──index.min.js
└──index.min.js.map
1directory,6files
測試驗證
新建demo.html進行測試
mkdirdemotouchdemo/demo.html
demo/demo.html
!DOCTYPEhtml
htmllang="en"
head
metacharset="UTF-8"
metahttp-equiv="X-UA-Compatible"content="IE=edge"
metaname="viewport"content="width=device-width,initial-scale=1.0"
titleDocument/title
/head
body
scriptsrc="../dist/umd/index.js"/script
scripttype="text/javascript"
console.log(loaf,'\n',loaf.Foo)
/script
/body
/html
用瀏覽器打開demo.html,然后F12打開控制臺,可以看到如下輸出則說明初步達成了目標:
Module{__esModule:true,Symbol(Symbol.toStringTag):'Module'}
demo.html:13?Foo(){
var_bar=arguments.length0arguments[0]!==undefinedarguments[0]:newBar();
src_classCallCheck(this,Foo);
this._bar=_bar;
}
輸出esm模塊
完成上面的步驟后,我們已經(jīng)到了一個umd模塊的輸出,相關(guān)文件都在dist/umd目錄下;其中包含可供CommonJsESMAMD模塊系統(tǒng)和script標簽使用的umd格式的javascript文件和一個單獨的css樣式文件.
已經(jīng)輸出了umd格式的js了,為什么還要輸出esm模塊----TreeShaking
TreeshakingisatermcommonlyusedintheJavaScriptcontextfordead-codeelimination.ItreliesonthestaticstructureofES2015modulesyntax,i.e.importandexport.ThenameandconcepthavebeenpopularizedbytheES2015modulebundlerrollup.
此庫的使用者也使用了類似webpack之類的支持TreeShaking
的模塊打包工具,需要讓使用者的打包工具能對這個js庫loaf進行死代碼優(yōu)化TreeShaking
從webpack文檔中看出,tree-shaking依賴于ES2015(ES2015modulesyntax,ES2015=ES6)的模塊系統(tǒng),tree-shaking可以對打包體積有不錯優(yōu)化,所以為了支持使用者進行tree-shaking,輸出esm模塊(esm模塊就是指ES2015modulesyntax)是很有必要的.
用tsc輸出esm和類型聲明文件
tsc-ptsconfig.json--declarationDir./dist/typings-mes6--outDirdist/lib-esm
上面的命令使用typescript編譯器命令行接口tsc輸出了ES6模塊格式的javascript文件到dist/lib-esm目錄下
將這個目錄加入到package.json的scripts配置中:
package.json
{
"name":"loaf",
"version":"1.0.0",
"description":"Ademoshowshowtocreatebuildajavascriptlibrarywithwebpacktypescript",
"main":"index.js",
"scripts":{
"build:umd":"webpack-cwebpack.config.ts--node-envproduction--envNODE_ENV=production",
"build:lib-esm":"tsc-ptsconfig.json--declarationDir./dist/typings-mes6--outDirdist/lib-esm",
"test":"npmruntest"
"keywords":[
"demo"
"author":"laggage",
"license":"MIT",
"devDependencies":{
"@babel/core":"^7.18.6",
"@babel/preset-env":"^7.18.6",
"@babel/preset-typescript":"^7.18.6",
"@types/node":"^18.0.0",
"@types/webpack":"^5.28.0",
"babel-loader":"^8.2.5",
"css-loader":"^6.7.1",
"css-minimizer-webpack-plugin":"^4.0.0",
"less":"^4.1.3",
"less-loader":"^11.0.0",
"mini-css-extract-plugin":"^2.6.1",
"postcss-loader":"^7.0.0",
"style-loader":"^3.3.1",
"terser-webpack-plugin":"^5.3.3",
"ts-node":"^10.8.2",
"typescript":"^4.7.4",
"webpack":"^5.73.0",
"webpack-cli":"^4.10.0"
}
然后運行:npmrunbuild:lib-esm,此時dist目錄結(jié)構(gòu)如下:
dist
├──lib-esm
│├──bar.js
│└──index.js
├──typings
│├──bar.d.ts
│├──bar.d.ts.map
│├──index.d.ts
│└──index.d.ts.map
└──umd
├──index.css
├──index.js
├──index.js.map
├──index.min.css
├──index.min.js
└──index.min.js.map
3directories,12files
多出了兩個子目錄分別為lib-esm和typings,分別放著es6模塊格式的javascript輸出文件和typescript類型聲明文件.
完善package.json文件
到目前為止,package.json的scripts配置中,已經(jīng)有了build:umd和build:lib-esm用于構(gòu)建umd格式的輸出和esm格式的輸出,現(xiàn)在我們再向添加一個build用來組合build:umd和build:lib-esm并進行最終的構(gòu)建,再次之前先安裝一個依賴shx,用于跨平臺執(zhí)行一些shell腳本:npmi-Dshx;
更新package.json文件:
package.json
{
"name":"loaf",
"version":"1.0.0",
"description":"Ademoshowshowtocreatebuildajavascriptlibrarywithwebpacktypescript",
"main":"index.js",
"scripts":{
"build":"shxrm-rfdist/**npmrunbuild:umdnpmrunbuild:lib-esm",
"build:umd":"webpack-cwebpack.config.ts--node-envproduction--envNODE_ENV=production",
"build:lib-esm":"tsc-ptsconfig.json--declarationDir./dist/typings-mes6--outDirdist/lib-esm",
"test":"npmruntest"
"keywords":[
"demo"
"author":"laggage",
"license":"MIT",
"devDependencies":{
"@babel/core":"^7.18.6",
"@babel/preset-env":"^7.18.6",
"@babel/preset-typescript":"^7.18.6",
"@types/node":"^18.0.0",
"@types/webpack":"^5.28.0",
"babel-loader":"^8.2.5",
"css-loader":"^6.7.1",
"css-minimizer-webpack-plugin":"^4.0.0",
"less":"^4.1.3",
"less-loader":"^11.0.0",
"mini-css-extract-plugin":"^2.6.1",
"postcss-loader":"^7.0.0",
"shx":"^0.3.4",
"style-loader":"^3.3.1",
"terser-webpack-plugin":"^5.3.3",
"ts-node":"^10.8.2",
"typescript":"^4.7.4",
"webpack":"^5.73.0",
"webpack-cli":"^4.10.0"
}
package.json文件生成typescript聲明文件所在的路徑(可以參考typescript官網(wǎng):Includingdeclarationsinyournpmpackage):
package.json
{
"name":"loaf",
"version":"1.0.0",
"description":"Ademoshowshowtocreatebuildajavascriptlibrarywithwebpacktypescript",
"main":"index.js",
"typings":"./typings",
"scripts":{
"build":"shxrm-rfdist/**npmrunbuild:umdnpmrunbuild:lib-esm",
"build:umd":"webpack-cwebpack.config.ts--node-envproduction--envNODE_ENV=production",
"build:lib-esm":"tsc-ptsconfig.json--declarationDir./dist/typings-mes6--outDirdist/lib-esm",
"test":"npmruntest"
"keywords":[
"demo"
"author":"laggage",
"license":"MIT",
"devDependencies":{
"@babel/core":"^7.18.6",
"@babel/preset-env":"^7.18.6",
"@babel/preset-typescript":"^7.18.6",
"@types/node":"^18.0.0",
"@types/webpack":"^5.28.0",
"babel-loader":"^8.2.5",
"css-loader":"^6.7.1",
"css-minimizer-webpack-plugin":"^4.0.0",
"less":"^4.1.3",
"less-loader":"^11.0.0",
"mini-css-extract-plugin":"^2.6.1",
"postcss-loader":"^7.0.0",
"shx":"^0.3.4",
"style-loader":"^3.3.1",
"terser-webpack-plugin":"^5.3.3",
"ts-node":"^10.8.2",
"typescript":"^4.7.4",
"webpack":"^5.73.0",
"webpack-cli":"^4.10.0"
}
package.json中添加exports配置聲明模塊導出路徑
package.json中的exports字段用于告訴使用者引用此庫時從哪里尋找對應(yīng)的模塊文件.比如使用者可能通過esm模塊引用此庫:
import{Foo}from'loaf';
constfoo=newFoo();
此時如果我們的package.json中沒有指定exports字段,那么模塊系統(tǒng)會去尋找node_modules/index.js,結(jié)果肯定是找不到的,因為我們真正的esm格式的輸出文件應(yīng)該是在node_modules/loaf/lib-esm中的
于是我們可以這樣來配置exports:
package.json
{
"name":"loaf",
"version":"1.0.0",
"description":"Ademoshowshowtocreatebuildajavascriptlibrarywithwebpacktypescript",
"main":"index.js",
"typings":"./typings",
"exports":{
"./*":"./lib-esm/*",
"./umd/*":"./umd"
"scripts":{
"build":"shxrm-rfdist/**npmrunbuild:umdnpmrunbuild:lib-esm",
"build:umd":"webpack-cwebpack.config.ts--node-envproduction--envNODE_ENV=production",
"build:lib-esm":"tsc-ptsconfig.json--declarationDir./dist/typings-mes6--outDirdist/lib-esm",
"test":"npmruntest"
"keywords":[
"demo"
"author":"laggage",
"license":"MIT",
"devDependencies":{
"@babel/core":"^7.18.6",
"@babel/preset-env":"^7.18.6",
"@babel/preset-typescript":"^7.18.6",
"@types/node":"^18.0.0",
"@types/webpack":"^5.28.0",
"babel-loader":"^8.2.5",
"css-loader":"^6.7.1",
"css-minimizer-webpack-plugin":"^4.0.0",
"less":"^4.1.3",
"less-loader":"^11.0.0",
"mini-css-extract-plugin":"^2.6.1",
"postcss-loader":"^7.0.0",
"shx":"^0.3.4",
"style-loader":"^3.3.1",
"terser-webpack-plugin":"^5.3.3",
"ts-node":"^10.8.2",
"typescript":"^4.7.4",
"webpack":"^5.73.0",
"webpack-cli":"^4.10.0"
}
用api-extractor提取出干凈的.d.ts
在上面的用tsc輸出esm和類型聲明文件這一段中,我們通過tsc命令輸出了typescript了類型聲明文件到dist/types目錄下,這個目錄下有兩個.d.ts文件,分別是bar.d.ts和foo.d.ts,通常是希望這些聲明文件都在一個文件index.d.ts中的,如果他們分散開了,以本庫為例,如果我要使用本庫中的Bar類,那么我可能需要這樣來導入:
import{Bar}from'loaf/typings/bar';
我不覺得的這種導入方式是好的做法,理想的導入方式應(yīng)該像下面這樣:
import{Bar}from'loaf';
所以接下來,還要引入微軟提供的api-extracto
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 消除艾梅乙傳播工作推進部署考核含答案
- 項目融資試題及答案
- 物業(yè)消防試題及答案
- 哈爾濱市第九中學校2025屆高三下學期第五次模擬考試英語試卷(不含音頻)
- 2025年湖南省長沙市中考歷史復習卷(1)含答案
- 語文●全國甲卷丨2022年普通高等學校招生全國統(tǒng)一考試語文試卷及答案
- 幕墻埋件錨栓拉拔試驗專題
- 智慧園區(qū)基于智慧園區(qū)場景的物聯(lián)網(wǎng)教學實訓體系建設(shè)方案
- 2025年中國手扶式掃地機行業(yè)市場前景預測及投資價值評估分析報告
- 2025年智能汽車應(yīng)用工程師職業(yè)技能認證模擬試卷(智能駕駛技術(shù)與應(yīng)用)-智能駕駛車輛傳感器技術(shù)
- 廣播電視節(jié)目評析期末考試資料
- 魚缸定做合同
- 2024-2030年中國凈水器行業(yè)市場深度調(diào)研及發(fā)展趨勢與投資前景研究報告
- GB/T 9799-2024金屬及其他無機覆蓋層鋼鐵上經(jīng)過處理的鋅電鍍層
- 重慶市沙坪壩區(qū)第八中學校2023-2024學年八年級下學期期末英語試題(解析版)
- 河南省2022-2023學年七年級下學期語文期末試卷(含答案)
- 霧化吸入團體標準解讀
- 【數(shù)字人民幣對貨幣政策的影響及政策探究12000字(論文)】
- 江蘇省鹽城市大豐區(qū)2023-2024學年八年級上學期期中數(shù)學試題(解析版)
- 衛(wèi)生監(jiān)督協(xié)管培訓課件
- 2.3.5 重力壩揚壓力計算示例講解
評論
0/150
提交評論