rollup和typescript搭建函数库

336 阅读5分钟

简介

在项目中会使用一些公共函数库,比如lodash,underscore等。当项目包很大时,需要做一些公共函数抽离,那此时做一个自己的公共函数库就很有必要了。

本篇文章用于介绍使用rollup工具构建自己的代码库,使用typescript编写代码,使用jest进行代码测试,使用vuepress编写说明文档。

依赖的库

  • rollup 是一个 JavaScript 模块打包器,可以将小块代码编译成大块复杂的代码,例如 library 或应用程序。
  • typescript javascript的超集,支持类型定义。
  • vuepress 极简静态网站生成器
  • jest 用于代码单元测试

初始化项目

  • 创建目录并初始化node项目
mkdir myTools 
cd myTools 
npm init -y
  • 安装rollup
npm install rollup -D
  • 创建modules目录,然后再在目录中创建入口文件index.ts
  • 之后创建rollup.config.js,配置如下:
import json from "rollup-plugin-json";
import sourceMaps from "rollup-plugin-sourcemaps";
import { terser } from 'rollup-plugin-terser';
import babel from "rollup-plugin-babel";
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import path from "path";

const libraryName = 'myTools';
const isDev = process.env.NODE_ENV !== 'production';

export default {
  input: "modules/index.ts",
  output: [
    {
      file: path.resolve(__dirname, './lib/main.esm.js'),
      format: "esm",
      sourcemap: true
    },
    {
      file: path.resolve(__dirname, './lib/main.umd.js'),
      format: "umd",
      name: libraryName,
      sourcemap: true,
      globals: {
        lodash: '_',// 指明 global.lodash 即是外部依赖 lodash
        dayjs: 'dayjs'
      }
    },
    {
      file: path.resolve(__dirname, './lib/main.amd.js'),
      format: 'amd',
      sourcemap: true
    },
    {
      file: path.resolve(__dirname, './lib/main.cjs.js'),
      format: 'cjs',
      sourcemap: true
    },
    {
      file: path.resolve(__dirname, './lib/main.iife.js'),
      format: 'iife',
      name: 'libraryName',
      globals: {
        lodash: '_',// 指明 global.lodash 即是外部依赖 lodash
        dayjs: 'dayjs'
      },
      sourcemap: true
    },
    {
      file: path.resolve(__dirname, './lib/main.system.js'),
      format: 'system',
      sourcemap: true
    }
  ],
  plugins: [
    sourceMaps(),
    !isDev && terser(),
    babel(),
    resolve(),//用于rollup无法引入第三方依赖
    commonjs(),//用于rollup无法引入第三方依赖
    json()
  ],
  external: ['lodash', 'jest-canvas-mock', 'dayjs'] //告诉rollup不要将此数组内容打包,而作为外部依赖
};

配置地址:www.rollupjs.com/guide/big-l…

amd – 异步模块定义,用于像RequireJS这样的模块加载器 
cjs – CommonJS,适用于 Node 和 Browserify/Webpack 
esm – 将软件包保存为 ES 模块文件,在现代浏览器中可以通过 <script type=module> 标签引入 
iife – 一个自动执行的功能,适合作为<script>标签。(如果要为应用程序创建一个捆绑包,您可能想要使用它,因为它会使文件大小变小。) 
umd – 通用模块定义,以amd,cjs 和 iife 为一体 
system - SystemJS 加载器格式
  • 然后在package.json文件中加入运行命令
{
    ...
    "scripts": {
        "dev":"rollup -c -w",
        "build": "rollup --config",
    }
    ...
}
  • 执行命令npm run build将自动打包代码到lib目录。

添加typescript支持

  • 安装支持库
npm install typescript rollup-plugin-typescript2 tslib -D
  • 修改rollup.config.js配置,添加typescipt插件
import typescript from "rollup-plugin-typescript2";
export default {
  input: "modules/index.ts",
  output: [ ... ],
  plugins: [
    typescript({
      exclude: "node_modules/**",
      typescript: require("typescript"),
      // 默认声明文件放到一个文件夹中
      useTsconfigDeclarationDir: true
    }),
  ],
};
  • 根目录下创建tsconfig.json文件,添加如下配置
{
    "compilerOptions": {
        "target": "es5",
        "module": "es2015",
        "lib": [
            "es2015",
            "es2016",
            "es2017",
            "dom"
        ],
        "sourceMap": true,
        // 开启声明文件的输出
        "declaration": true,
        // 开启声明文件输出目录
        "declarationDir": "types",
        // 指定默认的类型声明文件查找路径
        "typeRoots": [
            "node_modules/@types"
        ],
        // 模块解析策略是node
        "moduleResolution": "node",
        // 开启es与其他模块的交互
        "esModuleInterop": true,
    },
    "exclude": [
        "./lib",
        "node_modules/",
        "./test",
        "./types",
    ]
}

入口编写

项目结构搭建好后,就可以添加自己的工具函数,为了在单个js文件中导出,需要将所有函数通过index.ts导出。 这里我在modules目录中编写了4个工具函数,分别是clonecloneDeepdebouncethrottle。 我需要在index.ts中将所有函数导出,如下:

export { default as debounce } from "./debounce";
export { default as throttle } from "./throttle";
export { default as clone } from "./clone";
export { default as cloneDeep } from "./cloneDeep";

这样就能通过import { cloneDeep } from "myTools"引入函数了。

jest测试

接下来需要配置项目支持jest测试,保证代码正确性。

  • 先安装jest支持
npm install jest ts-jest @types/jest --save-dev
  • 在根目录创建jest.config.js文件
module.exports = {
  preset: "ts-jest",
  // testEnvironment: "node",
  "testEnvironment": "jsdom"
};
  • test目录,并添加xxx.spec.ts测试文件,内容如下:
test("测试1+1", () => {
  expect(1+1).toBe(2);
});
  • 接下来添加运行命令,在package.json中添加:
"test": "jest --no-cache" //测试单个文件执行 npm test -- xxx.spec.ts
  • 然后运行npm run test命令进行测试,jest语法详情见官网。

说明文档编写

  • 全局安装-vuepress
npm install -g vuepress 
  • 在根目录下创建一个docs文件
mkdir docs
  • 在package.json文件中添加脚本
{
  "scripts": {
    "dev": "vuepress dev docs",
    "build": "vuepress build docs"
  }
}
  • 进入docs文件夹中使用mkdir命令创建.vuepress文件夹,注意这个文件夹的名字时固定的,不要随便改变
cd docs
mkdir .vuepress

这个.vuepress主要就是我们用于存放全局的配置、组件、静态资源等与VuePress相关的文件配置都将会放在这里

具体更详细配置说明可见官网:基本配置具体更详细的目录树结构说明:目录结构至此,项目大体已经搭建完成了,接下来,主要就是一些配置。

  • 基本配置,进入.vuepress文件夹,创建config.js文件 添加如下配置
const sidebar = require("./sidebar");

module.exports = {
  title: '公共函数',
  description: 'Just playing around',
  themeConfig: {
    nav: [
      { text: '首页', link: '/' },
      { text: 'github', link: 'https://xxxxxx' },
    ],
    sidebar: sidebar
  }
}
  • 在.vuepress文件下创建sidebar.js文件,配置侧边栏
module.exports = {
  themeConfig:{
    sidebar:{
      {
       title: "JavaScript",
       collapsable: true,
       children: [
         ["js/", "目录"],
         ["js/scope", "理解Js中的作用域-作用域链以及闭包"]
       ]
      },
      {
        title: "工具",
        collapsable: true,
        children: [
          ["tools/", "目录"],
          ["tools/vuepress-build-blog", "手把手教你用vuepress搭建博客"]
        ]
       }
    }
  }
}
  • 首页配置 在docs下创建一个README.md文件,将首页内容填写进去。
# 哈喽,这里是首页

Npm本地调试

  • 在npm包下执行 npm link 这时候 会以package.json 里的name 为名字 将这个包挂载到全局。
  • 在项目中(需要引入npm包),执行npm link name。

Npm发布

npm login
npm publish

参考文档:

  1. juejin.cn/post/690156…
  2. juejin.cn/post/710926…
  3. juejin.cn/post/705123…
  4. juejin.cn/post/706955…
  5. juejin.cn/post/712468…
  6. juejin.cn/post/684490…
  7. juejin.cn/post/684490…
  8. juejin.cn/post/684490…
  9. blog.51cto.com/u_15548643/…
  10. lequ7.com/guan-yu-qia…
  11. jestjs.io/docs/gettin…
  12. coder.itclan.cn/fontend/too…
  13. blog.csdn.net/yehuozhili/…
  14. blog.csdn.net/weixin_5488…
  15. www.w3cschool.cn/jest_cn/jes…