




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第使用typescript+webpack构建一个js库的示例详解目录入口文件tsconfig配置webpack配置文件webpack入口文件配置webpack为typescript和less文件配置各自的loaderwebpack的output配置运行webpack进行打包测试验证输出esm模块已经输出了umd格式的js了,为什么还要输出esm模块----TreeShaking用tsc输出esm和类型声明文件package.json中添加exports配置声明模块导出路径完善package.json文件用api-extractor提取出干净的.d.ts配置使用APIextractor更新package.json用@internal标注只希望在内部使用的class小结记录使用typescript配合webpack打包一个javascriptlibrary的配置过程.
目标是构建一个可以同时支持CommonJs,esm,amd这个几个js模块系统的javascript库,然后还有一个单独打包出一个css的样式文件的需求.
为此以构建一个名为loaf的javascript库为例;首先新建项目文件目录loaf,并进入此文件目录执行npminit命令,然后按照控制台的提示输入对应的信息,完成后就会在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相关的东西,主要是需要babel-loader将编写的typescript代码转译成es5或es6已获得更好的浏览器兼容性ts-node@types/node@types/webpack:安装这几个包是为了能用typescript编写webpack配置文件(webpack.config.ts)mini-css-extract-pluginlessless-loader:编译提取less文件到单独的css文件的相关依赖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模块
//这样你的代码库中就可以统一的使用import导入依赖了,而不需要另外再使用require导入commonjs模块
"esModuleInterop":true,
//是否允许合成默认导入
//开启后,依赖的模块如果没有导出默认的模块
//那么typescript会帮你给该模块自动合成一个默认导出让你可以通过默认导入的方式引用该模块
"allowSyntheticDefaultImports":true,
//是否生成`.d.ts`的类型声明文件
"declaration":true,
//输出的目标js版本,这里用es6,然后配和babel进行转译才以获得良好的浏览器兼容
"target":"es6",
"allowJs":true,
"moduleResolution":"node",
"lib":["es2015","dom"],
"declarationMap":true,
//启用严格的null检查
"strictNullChecks":true,
//启用严格的属性初始化检查
//启用后类属性必须显示标注为可空或赋一个非空的初始值
"strictPropertyInitialization":true
"exclude":["node_modules"],
"include":["src/**/*"]
}
webpack配置文件
创建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入口是为了经过压缩后js和css文件,在生产环境使用一般都会使用.min.js结尾的文件以减少网络传输时的尺寸;实现这个还需要结合optimization相关配置,如下:
optimization:{
minimize:true,
minimizer:[
newTerserPlugin({test:/.min.js$/}),
newCssMinimizer({
test:/.min.css$/,
},
另外,index和index.min的值都是相同的entryFiles对象,这个对象是一个字符串数组,里面放的就是我们的入口文件相对路径,这里一定要注意把./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文件的相关依赖
上面的配置为.ts结尾的文件配置了babel-loader;为.less结尾的文件配置一串loader,使用了use,use中的loader的执行顺序是从后往前的,上面less的配置就是告诉webpack遇到less文件时,一次用less-loader-postcss-loader-css-loader-生产环境用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进行引用可以为不同的模块系统配置不同的导出模块名供客户端来进行引用;由于这里的导出模块名都是loaf,所以也可以直接设置成loaf.
运行webpack进行打包
现在回到最开始通过npminit生成的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",
"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,然后命令行到项目目录下执行npmrunbuild:umd,不出意外应该就构建成功了,此时生成的dist目录结构如下
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模块
完成上面的步骤后,我们已经到了一个umd模块的输出,相关文件都在dist/umd目录下;其中包含可供CommonJsESMAMD模块系统和script标签使用的umd格式的javascript文件和一个单独的css样式文件.
已经输出了umd格式的js了,为什么还要输出esm模块----TreeShaking
TreeshakingisatermcommonlyusedintheJavaScriptcontextfordead-codeelimination.ItreliesonthestaticstructureofES2015modulesyntax,i.e.importandexport.ThenameandconcepthavebeenpopularizedbytheES2015modulebundlerrollup.
此库的使用者也使用了类似webpack之类的支持TreeShaking
的模块打包工具,需要让使用者的打包工具能对这个js库loaf进行死代码优化TreeShaking
从webpack文档中看出,tree-shaking依赖于ES2015(ES2015modulesyntax,ES2015=ES6)的模块系统,tree-shaking可以对打包体积有不错优化,所以为了支持使用者进行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目录结构如下:
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配置中,已经有了build:umd和build:lib-esm用于构建umd格式的输出和esm格式的输出,现在我们再向添加一个build用来组合build:umd和build:lib-esm并进行最终的构建,再次之前先安装一个依赖shx,用于跨平台执行一些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官网: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字段用于告诉使用者引用此库时从哪里寻找对应的模块文件.比如使用者可能通过esm模块引用此库:
import{Foo}from'loaf';
constfoo=newFoo();
此时如果我们的package.json中没有指定exports字段,那么模块系统会去寻找node_modules/index.js,结果肯定是找不到的,因为我们真正的esm格式的输出文件应该是在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';
我不觉得的这种导入方式是好的做法,理想的导入方式应该像下面这样:
import{Bar}from'loaf';
所以接下来,还要引入微软提供的api-extracto
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 上海建设管理职业技术学院《外汇交易模拟》2023-2024学年第二学期期末试卷
- 福州英华职业学院《园林建筑设计Ⅱ》2023-2024学年第二学期期末试卷
- 宁夏幼儿师范高等专科学校《副教学训练理论与实践(1)》2023-2024学年第二学期期末试卷
- 北京理工大学《建筑消防设备工程》2023-2024学年第二学期期末试卷
- 西安航空职业技术学院《自动控制原理B实验》2023-2024学年第二学期期末试卷
- 潍坊食品科技职业学院《德育原理》2023-2024学年第二学期期末试卷
- 广州涉外经济职业技术学院《意识形态前沿问题研究》2023-2024学年第二学期期末试卷
- 民办合肥财经职业学院《精神病护理学》2023-2024学年第二学期期末试卷
- 赣州师范高等专科学校《面向对象程序设计-JAVA语言》2023-2024学年第二学期期末试卷
- 天津外国语大学《原理与应用实训》2023-2024学年第二学期期末试卷
- 2024-2030年中国餐饮连锁行业发展状况及投资经营模式分析报告
- 中储粮安全生产培训
- 2024年江西省公务员录用考试《行测》试题及答案解析
- 2024年财会业务知识竞赛题库及答案(600题)
- DB11T 1470-2022 钢筋套筒灌浆连接技术规程
- 2024秋期国家开放大学专科《EXCEL在财务中的应用》一平台在线形考(形考作业一至四)试题及答案
- 现金日记账模板(出纳版)
- 临床常见操作-灌肠
- 探寻中国茶:一片树叶的传奇之旅学习通超星期末考试答案章节答案2024年
- 检验科降低检测报告超时率PDCA持续改进案例
- 冷却塔清洗合同模板
评论
0/150
提交评论