JSSDK开发思路,基于RollupJS记录

2,584 阅读4分钟

背景

项目需要开发一个发版通知插件,同时公司项目属于乾坤架构的微前端应用,涉及多个子应用,如果每个项目都写一遍逻辑,在修改时可能会重复修改多个项目,于是想着能不能通过开发一个插件,对项目侵入最少方式,插件升级后依赖项目npm i一下就可以了。

调研

待编

行动

基于Rollup开发一个插件,起步还是建议先阅读一遍官网的介绍,以便对它有一个基本的了解。

RollupJS 官网

但是官网的资料很多有坑(因为版本更新然后没有人更新官网资料导致……),所以如果全部按官网的指导走,是走不下去的,一堆问题。

最明显的一个就是 babel,官网说明默认是 babel6,但如果直接从 npm 执行安装,默认安装 babel 则是 7+,配置起来完全不是一个世界的东西……

包括搜到的很多博文也都是过期状态,无法参考,所以决定写个分享来汇总下这次遇到的问题和一些可复用的配置。

注:以下大部分操作都是依赖于命令行操作,Windows 你可以用你熟悉的 cmd 或者 powerShell 或者我熟悉的 cmder ,macOS 可以用终端等等

创建项目

Rollup 只是个工具,不是脚手架,所以没有自己的创建命令,需要走传统的项目生成方法去创建。

    mkdir rollup-demo && cd rollup-demo

初始化项目

执行 npm init 命令,一路回车,生成package.json 文件。

建议把入口文件设置为src/main.js,因为实际项目会有很多个分文件,包括你自己编写的lib文件、config文件等,统一放在src下面进行归类管理。

然后打开package.json文件在scripts字段下新增build命令:

 "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "rollup -c rollup.config.js"
  },

安装依赖

npm install --save-dev rollup @rollup/plugin-node-resolve @rollup/plugin-babel @rollup/plugin-commonjs @rollup/plugin-json @rollup/plugin-alias rollup-plugin-terser rollup-plugin-banner @babel/core @babel/plugin-proposal-class-properties @babel/preset-env

各个包的作用如下

基础包名作用用途补充说明
rollupRollup 的核心包
@rollup/plugin-node-resolveRollup 插件包,帮助 Rollup 识别 node_modules 的包
@rollup/plugin-babelRollup 插件包,自动化解决 babel 的转换问题你可以更爽的写 ES6 以上的新语法…
@rollup/plugin-commonjsRollup 插件包,可将 CommonJS 模块转换为 ES6大部分 npm 包都是 CommonJS,比如常用的 axios/qs 库,如果你项目里用到了他们,不引入这个插件的话会构建失败
@rollup/plugin-jsonRollup 插件包,可将.json 文件转换为 ES6 模块比如:作为类库当然要涉及到版本更新,版本号肯定不能各种地方都手写,这种情况下就可以从 package.json 读取
@rollup/plugin-aliasRollup 插件包,配置路径别名alias 的作用大家都懂,开发环境必备
rollup-plugin-terserRollup 插件包,混淆压缩 js 代码打包发布必备
rollup-plugin-bannerRollup 插件包,给打包后的文件添加注释一般可以添加开发者信息、版本号等信息
@babel/core@rollup/plugin-babel 的依赖包,该插件基于 babel7
@babel/plugin-proposal-class-properties@rollup/plugin-babel 的依赖包,该插件基于 babel7
@babel/preset-env@rollup/plugin-babel 的依赖包,该插件基于 babel7

配置文件

上面提到修改了 package.json 的 script 字段,修改的含义是告知 node 在执行 build 命令的时候,通过 rollup 命令去运行一个叫 rollup.config.js 的配置文件(-c 是–config 的缩写)

import resolve from '@rollup/plugin-node-resolve'
import babel from '@rollup/plugin-babel'
import commonjs from '@rollup/plugin-commonjs'
import json from '@rollup/plugin-json'
import alias from '@rollup/plugin-alias'
import { terser } from 'rollup-plugin-terser'
import banner from 'rollup-plugin-banner'

const path = require('path')
const resolveDir = (dir) => path.join(__dirname, dir)

export default {
  input: 'src/main.js',
  output: [
    {
      file: `demo/js/demo.js`,
      format: 'umd',
      name: 'demo',
    },
    {
      file: `dist/${process.env.npm_package_version}/demo.min.js`,
      format: 'umd',
      name: 'demo',
      plugins: [terser()],
    },
  ],
  plugins: [
    resolve({
      browser: true,
    }),
    babel({
      babelHelpers: 'bundled',
    }),
    commonjs(),
    json(),
    alias({
      entries: [{ find: '@', replacement: resolveDir('src') }],
    }),
    banner(
      `name: <%= pkg.name %>\nversion: v<%= pkg.version %>\nauthor: <%= pkg.author %>`
    ),
  ],
}

这份配置的功能是,在执行了 npm run build 之后,会在 dist 文件夹里,生成一个 “版本号” 文件夹,版本号文件夹下是一个被压缩混淆了的版本。

同时在 demo 的 js 文件夹下,会生成一个没有混淆的版本用于 demo 的开发调试。

核心配置选项说明:

字段作用
input入口文件
output出口文件,一个数组,支持打包多个版本(通常是一个完整版开发,一个混淆压缩上线)
output.file出口的文件名,需要包含到文件夹里就把路径也写上,上面的 ({}).npm_package_version 是以版本号为文件夹归类发布
output.format输出格式:amd=异步模块、cjs=CommonJS、es=ES 模块文件、iife=自动执行、umd=通用模块(包含 amd/cjs/iife 为一体)
output.name暴露的全局变量,可以通过 window.xxx 来访问你的类库,类似 window.jQuery 的作用
output.plugins打包插件,目前只配置了一个 terser 用于打包一个压缩版本发布

完整配置项请参考Rollup官网

编译打包

开发阶段你可以根据自己的习惯使用各种 npm 包、自己写的 lib/module 文件等等,但是最终都需要在 main.js 导出一个变量

class Demo {
  sayHi(name) {
    console.log(`Hi, ${name}`)
  }
}

const demo = new Demo()

export default demo

这样使用的人就可以在引入你打包好的文件之后,通过这个变量去使用你的类库里的方法,觉得有点绕?看看最后的例子。

Babel配置

因为开发阶段会使用大量的 ES6 等浏览器还不完全兼容的新特性,或者引入一些第三方库,比如 axios 之类的,对于低版本 IE 还不太友好,这些情况下都需要进行 Babel 转换。

命名为 .babelrc 保存到项目根目录下

{
  "presets": [
    [
      "@babel/preset-env",
      {
        "modules": false,
        "targets": {
          "browsers": "> 1%, IE 11, not op_mini all, not dead"
        },
        "useBuiltIns": "usage",
        "corejs": 2
      }
    ]
  ],
  "plugins": [
    "@babel/plugin-proposal-class-properties"
  ]
}

🌰

我在 main.js 编写一个简单的函数,通过预设好的 demo 变量名打包导出。

dist 文件夹是最终要发版的混淆压缩版,每个版本都有独立的归类;demo 文件夹是用于开发调试的,这里的是未混淆的版本。

image.png

image.png

image.png

微信的 JSSDK 也是类似的用法 wx.config(options); 、wx.chooseImage() 等等

如何快速测试开发插件: 使用npm软链接本地开发快速导入到node-module下

后面会分享一下网页新版本发布后,提示用户刷新网页的插件开发。

引用 chengpeiquan.com/article/rol…