参考日期js库date-fns的github
导出的入口文件是由脚本生成的
封装工具库或是组件库时,我们需要追求按需导出按需导入,支持tree-shaking的esm模式
关于esm如何支持tree-shaking
- treeShaking原理
👇 导出的文件内容需要是这种语句
js
// This file is generated automatically by `scripts/build/indices.ts`.
export { default as add } from './add/index'
export { default as addBusinessDays } from './addBusinessDays/index'
export { default as addDays } from './addDays/index'
// ...
node不能直接运行ts,如何在node环境使用ts?
让node直接运行ts
ts
#!/usr/bin/env yarn ts-node
/**
* @file
* The script generates index files for submodules.
*/
import { writeFile } from 'fs/promises' // TODO: node内置模块promises?
import getFileList from '../_lib/getFileList'
interface File {
name: string
path: string
fullPath: string
}
// 传入目录信息生成文件内容
function generateIndex(
files: File[],
): string {
// 根据目录信息写入js语句
const lines = files.map(
(file) => `export { default as ${file.name} } from '${file.path}/index'`
)
// 添加注释和换行
return `// This file is generated automatically by \`scripts/build/indices.ts\`.
${lines.join('\n')}
`
}
// 立即执行函数
;(async () => {
// 生成目录信息
const fileList = await getFileList()
writeFile('src/index.ts', generateIndex(fileList))
})()
👇 根据src文件夹生成目录信息
js
// lib/getFileList
const path = require('path')
const fs = require('fs')
const { promisify } = require('util') // promisify把node内置模块方法转为promise...用node同步方法不就行了吗..
const exists = promisify(fs.exists)
const readDir = promisify(fs.readdir)
const ignorePattern = /^_|\./ // can't start with `_` or have a `.` in it
const ignoredDirs = ['locale', 'esm', 'fp', 'constants']
async function getFileList() {
const srcPath = path.join(process.cwd(), 'src')
const files = await readDir(srcPath)
// 根据目录生成路径信息
return Promise.all(
files
.filter(
// 过滤忽略目录
(file) => !ignorePattern.test(file) && !ignoredDirs.includes(file)
)
.map(async (file) => {
// 存在ts就使用ts,否则输入js的目录
const isTs = await exists(path.join(srcPath, file, 'index.ts'))
return {
name: file,
path: `./${file}`,
fullPath: `./src/${file}/index.${isTs ? 'ts' : 'js'}`,
}
})
)
}
module.exports = getFileList
生成组件库目录同理如👇 TODO: