开发一个适用于 nodejs 与浏览器的 npm 包 - 基于 rollupjs

栏目: Node.js · 发布时间: 5年前

内容简介:关于rollupjs 的教程已经非常多了,可是较少看到比较完整的工程样板,所以分享下我自己搭建的,已经在公司内部使用的样板工程。现在的前端为了打包一个插件,差不多下面的配置文件都是必须的;哪怕代码仅仅一百多行,为了保证质量,少了谁都不能少了下面的配置文件;

关于rollupjs 的教程已经非常多了,可是较少看到比较完整的工程样板,所以分享下我自己搭建的,已经在公司内部使用的样板工程。

先认识下目录结构

现在的前端为了打包一个插件,差不多下面的配置文件都是必须的;

哪怕代码仅仅一百多行,为了保证质量,少了谁都不能少了下面的配置文件;

如果是 typescript 写的,那就还要再加几个,怀念几年前 Happy Coding 的日子:grinning:。

Project/
├── README.md
├── package.json
├── rollup.config.js  
├── babel.config.js
├── bundle-analyzer-report.html        构建分析报告
├── jsdoc.json                         自动生成 api 文档
├── .gitignore
├── .eslintrc.js                        代码检查
├── .eslintignore                     
├── .editorconfig                       统一编辑器风格用的配置文件
├── coverage/                           测试覆盖率
├── dist/                               输出目录
├── dist-docs/                          文档输出目录
├── .vscode/                            vscode 编辑器配置目录
├── src/                                
|   ├── index.esm.js                    esm 输出用  
|   └── index.js                        cjs 和 umd 输出用
└── test/
    ├── fixtures/
    ├── unit/
    └── .eslintrc.js
复制代码

一、选择输出文件格式

因为要支持 nodejs 与浏览器,所以需要输出多种格式的文件,常见的输出格式是 cjs , esmumd 三种格式,如果有必要也可以在加上 iife 的格式。

  1. cjsnodejs 风格的文件,主要是为了给 node 端使用,属于commonjs 规范
function foo () {}

exports.foo = foo
// or 
module.exports = { foo }
复制代码
  1. esm 搭配 pkg.module 字段 主要是构建工具(webpack, rollupjs)在用,属于es module 规范
export function foo () {}

// or
export { foo }
复制代码
  1. umd 就是个万金油,不管是浏览器和 nodejs,有或没有模块加载器,都可以正常使用,属于 umd 规范
(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(['exports', 'b'], function (exports, b) {
            factory((root.commonJsStrictGlobal = exports), b);
        });
    } else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
        // CommonJS
        factory(exports, require('b'));
    } else {
        // Browser globals
        factory((root.commonJsStrictGlobal = {}), root.b);
    }
}(typeof self !== 'undefined' ? self : this, function (exports, b) {
    // Use b in some fashion.

    // attach properties to the exports object to define
    // the exported module properties.
    exports.action = function () {};
}));
复制代码
  1. iife 格式就是自执行文件,以前比较常见,主要是为了进行闭包和隔离代码的作用域,不知道是什么规范
(function () {
    // 代码写这里
}())
复制代码

推荐输出:cjs, esm 和 umd 三种格式的文件

二、 选择 rollupjs 插件

1. 选择代码转换插件(浏览器兼容用)

推荐babel 和buble,具体选择看个人选择,这里给出我选择的理由

babel 的使用场景

  1. 在项目中使用,需要兼容的浏览器种类比较多
  2. 用到最新的 ECMAScript 语法,比如 async/await 等

buble 的使用场景

  1. 环境可控的情况下,搭配构建 工具 使用
  2. 不需要考虑最新的语法,(截止 2019/05/02,不支持 async/await 和 class properties 语法转换)
  3. 期望编译后的代码较少(主要是助手函数代码)

目前两种都在用, babel 用于项目,buble 用于插件,因为插件可以进行后编译处理,免去代码冗余的问题

2. 选择测试框架

推荐一:

断言工具用 nodejs 自带的assert 或其他的都可以

推荐二:

真心好用,可惜还没有去深入了解,正在入手中

没有 e2e 的推荐,因为我也不熟

3. 其他插件

// 清理文件
import clear from 'rollup-plugin-clear'

// 执行进度(可选)
import progress from 'rollup-plugin-progress'

// 代码检查
import { eslint } from 'rollup-plugin-eslint'

// 去除不需要打包的外部依赖
import externals from 'rollup-plugin-node-externals'

// 字符串替换,类似 webpack 的 DefinePlugin
import replace from 'rollup-plugin-replace'

// 模块引用
import commonjs from 'rollup-plugin-commonjs'
import resolve from 'rollup-plugin-node-resolve'

// json 文件处理(可选)
import json from 'rollup-plugin-json'

// 代码压缩
import { terser } from 'rollup-plugin-terser'

// 查看构建后的文件大小
import filesize from 'rollup-plugin-filesize'

// 用于分析构建后的代码
import visualizer from 'rollup-plugin-visualizer'
复制代码

三、编写开发与构建配置

1. 配置 package.json

{
  // nodejs 入口 
  "main": "./dist/lib.commonjs.js",
  // webpack,rollupjs 入口
  "module": "./dist/lib.esm.js",
  "scripts": {
    // 用 cross-env 解决不同操作系统之间环境变量设置方式不一致的问题
    "dev": "cross-env NODE_ENV=development rollup -cw rollup.config.js",
    "build": "cross-env NODE_ENV=production rollup -c rollup.config.js"
  }
}
复制代码

2. 配置 rollup.config.js

rollupjs 支持输出对象或数组形式的配置,所以不需要拆分成多个配置文件.

const isProd = process.env.NODE_ENV === 'production'

// 配置输出格式
export default mergeConfig(baseConfig, [
  {
    input: 'src/index.esm.js',
    output: {
      banner,
      file: 'dist/lib.esm.js',
      format: 'es'
    }
  },
  {
    input: 'src/index.js',
    output: {
      file: 'dist/lib.commonjs.js',
      format: 'cjs'
    }
  },
  {
    input: './src/index.js',
    output: {
      file: `./dist/lib${isProd ? '.min' : ''}.js`,
      format: 'umd'
    },
    plugins: [
      isProd && terser(),
      process.env.npm_config_report && visualizer({
        title: `${pkg.name} - ${pkg.author.name}`,
        filename: 'bundle-analyzer-report.html'
      })
    ]
  }
])
复制代码

3. 配置 babel.config.js

module.exports = {
  presets: [
    ['@babel/preset-env',{
        // rollupjs 会处理模块,所以设置成 false
        modules: false
    }]
  ],
  plugins: [
     // 避免 babel 将 async/await 转成 Generator
     // 这样兼容性更好
    'transform-async-to-promises'
  ]
}
复制代码

4. 配置 .eslintrc.js

module.exports = {
  root: true,
  env: {
    // 用于跳过各自环境的全局变量,也可以分开使用 node 和 browser 属性
    'shared-node-browser': true,
    es6: true
  },
  rules: {
    // 构建时避免 console 和 debugger 被一起构建上去
    'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
  },
  // 为了语法解析
  parserOptions: {
    parser: 'babel-eslint',
    sourceType: 'module'
  }
}
复制代码

5. 查看效果

# 执行构建命令
$ npm run build --report
复制代码
开发一个适用于 nodejs 与浏览器的 npm 包 - 基于 rollupjs
# 执行构建命令并且生成 html 报告
$ npm run build --report
复制代码
开发一个适用于 nodejs 与浏览器的 npm 包 - 基于 rollupjs

四、编写测试配置

1. 配置 package.json

{
  "scripts": {
    // test 还可能包含测试数据文件,所以不能直接使用通配符
    "test": "cross-env NODE_ENV=test nyc mocha \"test/{**/*,*}.test.js\"",
    "report": "nyc report --reporter=html"
  },
  // 配置 nyc 插件
  "nyc": {
    "require": [
      // 为了能跑 es6 的代码
      "@babel/register"
    ],
    "reporter": [
      "text-summary"
    ]
  }
}
复制代码

2. 配置 test/.eslintrc

{
  "env": {
    // eslint 预设了 mocha 的全局变量,所以设置为 true 就可以了
    "mocha": true
  }
}
复制代码

注意 eslint 的配置会继承项目根目录的 eslint 的配置信息

3. 配置 babel.config.js

const pkg = require('./package.json')

module.exports = {
  presets: [
    ['@babel/preset-env', {
      // 测试时模块需要转换
      modules: process.env.NODE_ENV === 'test' ? 'commonjs' : false
    }]
  ],
  // 配置测试时用到的插件
  env: {
    test: {
      plugins: [
        'istanbul',
        'inline-json-import',
        // 路径别名,不然就只能用长长的路径进行模块引用了
        ['module-resolver',
          {
            root: ['./src/'],
            alias: {
              [pkg.name]: './src/index.esm.js'
            }
          }
        ]
      ]
    }
  }
}
复制代码

4. 查看效果

# 运行测试命令
$ npm test
复制代码
开发一个适用于 nodejs 与浏览器的 npm 包 - 基于 rollupjs
# 查看测试报告
$ npm run report
复制代码
开发一个适用于 nodejs 与浏览器的 npm 包 - 基于 rollupjs

五、添加 API 生成工具

这里使用的是jsdoc 工具

1. 配置 package.json

{
  "scripts": {
    "build:docs": "jsdoc -c jsdoc.json"
  }
}
复制代码

2. 配置 jsdoc.json

{
  "source": {
    "include": ["src"]
  },
  "templates": {
    "cleverLinks": false,
    "monospaceLinks": false
  },
  "tags": {
    "allowUnknownTags": false
  },
  "opts": {
    "verbose": true,
    "recurse": true,
    "encoding": "utf8",
    "readme": "README.md",
    "destination": "dist-docs",
     // 建议添加,因为这样可以一个版本一个文档
    "package": "package.json"
  }
}
复制代码

3. 写注释

开发一个适用于 nodejs 与浏览器的 npm 包 - 基于 rollupjs

4. 查看效果

开发一个适用于 nodejs 与浏览器的 npm 包 - 基于 rollupjs
开发一个适用于 nodejs 与浏览器的 npm 包 - 基于 rollupjs

六、非开发配置

还可以做的事情有:

  1. 版本号更新的前后处理
  2. git 提交前的代码检查
  3. changelog 自动生成

这些都是需要人工去配置的,当全部配置完毕后,一个拥有完善功能的项目也就配置完毕,这样的项目才可以被认为是一个工程了吧。

开发一个适用于 nodejs 与浏览器的 npm 包 - 基于 rollupjs

最后献上我的 github 地址,欢迎 fork

github.com/zhengxsFE/s…


以上所述就是小编给大家介绍的《开发一个适用于 nodejs 与浏览器的 npm 包 - 基于 rollupjs》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Hacking Growth

Hacking Growth

Sean Ellis、Morgan Brown / Crown Business / 2017-4-25 / USD 29.00

The definitive playbook by the pioneers of Growth Hacking, one of the hottest business methodologies in Silicon Valley and beyond. It seems hard to believe today, but there was a time when Airbnb w......一起来看看 《Hacking Growth》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

URL 编码/解码
URL 编码/解码

URL 编码/解码

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试