1.0.5 • Published 2 years ago

chengdaohua-ui v1.0.5

Weekly downloads
-
License
ISC
Repository
-
Last release
2 years ago

微信截图_20220702224234.png

rollup是什么

Rollup 是一个 JavaScript 模块打包器,可以将小块代码编译成大块复杂的代码,例如 library 或应用程序。 我们熟知的Vue、React等诸多知名框架或类库都是通过rollup.js进行打包的。 与Webpack偏向于应用打包的定位不同,rollup.js更专注于Javascript类库打包。 webpack对于代码分割和静态资源导入有着“先天优势”,并且支持热模块替换(HMR),而rollup并不支持。 所以当开发应用时可以优先选择webpack,但是rollup对于代码的Tree-shaking和ES6模块有着算法优势上的支持,若你项目只需要打包出一个简单的bundle包,并是基于ES6模块开发的,可以考虑使用rollup。

模块化

  • CommoneJS:module.exports,require() ,同步引用,编译时加载
  • AMD:非同步加载,前置依赖,浏览器环境要加载资源,实现者 require.js,Node使用;
  • CMD:非同步加载,就近依赖,延迟加载,实现者sea.js ;
  • ESM:exports,import,异步引用,运行时加载,以及Tree-shakeable的特性,因此被广泛使用;
  • UMD:是一种思想,兼容commonjs、AMD、CMD。

commonjs、AMD、CMD、ES6 Module、UMD区别:https://juejin.cn/post/6977604469794013197

快速上手

npm i rollup -g

目录准备(hello world)

├── lib # 编译结果
├── packages # 组件集合
│   └── hpic
├── package.json
└── rollup.config.js # rollup配置

配置

  "name": "chengdaohua-ui",
  "version": "1.0.2",
  "description": "hobby组件",
  "main": "lib/main/index.js",
  "private": false,
  "scripts": {
    // 通过config配置文件运行
    // "build": "rollup -c",
    // 通过直接指令运行
    "build": "rollup src/index.js -f umd -o dist/bundle.js",
    // -w 是指watch监听,实时编译
    "serve": "cross-env NODE_ENV=dev rollup -c -w",
    "serve:prod": "cross-env NODE_ENV=production rollup -c -w",
    "lib": "cross-env NODE_ENV=production rollup -c",
  },
  "author": "chengdaohua",
   // 指定npm push发布的文件
  "files": [
    "package.json",
    "README.md",
    "LICENSE",
    "lib"
  ],
import fs from 'fs';
import path from 'path';
// import autoInstall from '@rollup/plugin-auto-install'; // 自动安装由包导入的依赖项,即使还没有在package.json
import json from '@rollup/plugin-json'; // 将json文件转换为esm模块
import vue from 'rollup-plugin-vue'; // Vue文件编译
import postcss from 'rollup-plugin-postcss'; // css、less、scss编译
import { terser } from 'rollup-plugin-terser'; // js压缩
import commonjs from '@rollup/plugin-commonjs'; // 将 CommonJS 模块转换为 ES6
import { nodeResolve } from '@rollup/plugin-node-resolve'; // 文件resolve,可省略/index.js等
import babel from '@rollup/plugin-babel'; // babel转译es6、es7=>es5
import peerDepsExternal from 'rollup-plugin-peer-deps-external'; // 设置打包外部引用的依赖,不混入
import autoprefixer from 'autoprefixer'; // css兼容,搭配package.json里browserslist使用
import cssnano from 'cssnano'; // 压缩css代码
// import image from '@rollup/plugin-image';  // 图片转base64,配置项未生效,改为@rollup/plugin-url
import url from '@rollup/plugin-url'; // 可以将文件导入为 data-URIs 或 ES Modules,比如复制图片
import copy from 'rollup-plugin-copy'; // 文件拷贝
import replace from '@rollup/plugin-replace'; // 打包时替换
import alias from '@rollup/plugin-alias'; // import alias
import builtins from 'rollup-plugin-node-builtins';
// import globals from 'rollup-plugin-node-globals';

const nodeEnv = process.env.NODE_ENV;
const isProd = process.env.NODE_ENV === 'production'; // 生产环境判断

部分插件介绍

文件引用

// 不配置 @rollup/plugin-node-resolve 插件引入方式
export foo from './foo/index.js'
import bar from './bar/index.js'
// 配置了 @rollup/plugin-node-resolve 插件引入方式
export foo from './foo'
import bar from './bar'
// 对应webpack的设置, 默认寻找--按照设置的格式
resolve: {
  extensions: ['.js', '.jsx', '.vue'],
}

文件复制

// copy文件及目录  https://npmmirror.com/package/rollup-plugin-copy

配置/使用

功能支持

  • 支持外链Vue和安装Vue
  • 支持全量引用和按需引用
  • 支持组件内按需引入第三方组件,例如Vant的van-button组件
  • 支持公共方法自动挂在到Vue.prototype下
  • 支持小图片(<10kb)自动转base64格式
  • 支持umd和es格式输出
  • 支持指定包(Vue,vant等)不编入UI库
  • 支持less、scss编译成css单独抽离打包
  • 支持组件库require引用外部包的方式
  • 支持alias定义,比如js引用路径通过@
  • 支持js和css压缩

组件库示例

示例ui库名称:chengdoahua-ui 发布于npm官方:https://www.npmjs.com/package/chengdaohua-ui 示例组件:hpic

<template>
  <div class="video">
    <van-image :width="width" :height="height" :src="imgUrl || img" />
  </div>
</template>

<script>
import img from "./2.jpg";

export default {
  name: "Hpic",
  props: {
    imgUrl: {
      type: String,
      default: '',
    },
    width: {
      type: [String, Number],
      default: 100,
    },
    height: {
      type: [String, Number],
      default: 100,
    },
  },
  data() {
    return {
      img: img,
    };
  },
};
</script>

示例公共方法:haxios、haddScript

import haxios from './request';
import haddScript from './addScript';

const utils = { haxios, haddScript };
const useFn = function (arr) {
  (arr || []).forEach((e) => {
    Vue.prototype[e] = utils[e];
  });
};
export default useFn;

切换到npm官方源

npm config set registryhttp://registry.npm.taobao.org/

全量引用

// 全量引用
const Vue = window.Vue;  // 外链引用Vue
import Vue from 'vue' // 安装引用Vue
import "chengdaohua-ui";  // 外链引入Vue,则直接引入,自动install所有组件
import {utils} from "chengdaohua-ui";  // 加载工具库
import main from 'chengdaohua-ui'; // 加载所有组件,通过use生效
import 'chengdaohua-ui/lib/main/index.css'; // 全量引入样式
Vue.use(main);
utils(['haxios'])  // 公共方法自动挂在到Vue.prototype
// 直接引用
<Hpic width="400" imgUrl="https://www.rollupjs.com/img/favicon.png"></Hpic>

按需引入

配置babel 新建babel.config.js文件,配置vant和chengdaohua-ui,目的是支持按需加载,原理同element、vant

// 根目录新增文件
module.exports = {
  presets: [
    '@vue/cli-plugin-babel/preset'
  ],
  plugins: [
    ['import', {
      libraryName: 'vant',
      libraryDirectory: 'es',
      style: true
    }, 'vant'],
    [
      'import',
      {
        libraryName: 'chengdaohua-ui',
        customName(name) {
          return `chengdaohua-ui/lib/${name}/${name}-es.js`
        },
        customStyleName(name) {
          return `chengdaohua-ui/lib/${name}/${name}-es.css`
        },
      },
      'chengdaohua-ui',
    ],
  ]
}
import Vue from 'vue'
import {hpic} from "chengdaohua-ui";  // 加载指定组件hpic
import {utils} from "chengdaohua-ui";  // 加载工具库

Vue.use(hpic) // 全局引用单个组件,外链引用可不写
utils(['haxios'])  // 公共方法自动挂在到Vue.prototype
// 直接引用
<Hpic width="400" imgUrl="https://www.rollupjs.com/img/favicon.png"></Hpic>

import {hpic} from "chengdaohua-ui"; // 组件内单独引用单个组件
components: {Hpic}, // 外链引入Vue可不写

优化

  • 减少打包文件的数量
  • 减少不必要的执行函数
  • 增加打包缓存,进行增量打包
  • 由单线程变为多线程

打包时排除外部包的引用

  1. 直接配置

external: 'vue', // 告诉rollup,不打包vue;将其视为外部依赖

  1. 通过rollup-plugin-peer-deps-external插件排除

package.json里添加peerDependencies,添加打包时要排除的外部引用 设置includeDependencies,所有Dependencies都不会被打包 微信图片_20220703010500.png

完整配置

{
  "name": "chengdaohua-ui",
  "version": "1.0.2",
  "description": "hobby组件",
  "main": "lib/main/index.js",
  "private": false,
  "scripts": {
    "dev": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint --fix",
    "serve": "cross-env NODE_ENV=dev rollup -c -w",
    "serve:prod": "cross-env NODE_ENV=production rollup -c -w",
    "lib": "cross-env NODE_ENV=production rollup -c",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "files": [
    "package.json",
    "README.md",
    "LICENSE",
    "lib"
  ],
  "devDependencies": {
    "@babel/core": "^7.18.6",
    "@babel/eslint-parser": "^7.12.16",
    "@babel/helpers": "^7.18.6",
    "@babel/preset-env": "^7.18.6",
    "@rollup/plugin-alias": "^3.1.9",
    "@rollup/plugin-auto-install": "^2.2.0",
    "@rollup/plugin-babel": "^5.3.1",
    "@rollup/plugin-commonjs": "^22.0.1",
    "@rollup/plugin-image": "^2.1.1",
    "@rollup/plugin-json": "^4.1.0",
    "@rollup/plugin-node-resolve": "^13.3.0",
    "@rollup/plugin-replace": "^4.0.0",
    "@rollup/plugin-url": "^7.0.0",
    "@vue/cli-plugin-babel": "~5.0.0",
    "@vue/cli-plugin-eslint": "~5.0.0",
    "@vue/cli-service": "~5.0.0",
    "autoprefixer": "^10.4.7",
    "babel-plugin-import": "^1.13.5",
    "cross-env": "^7.0.3",
    "cssnano": "^5.1.12",
    "eslint": "^7.32.0",
    "eslint-plugin-vue": "^8.0.3",
    "postcss": "^8.4.14",
    "rollup": "^2.75.7",
    "rollup-plugin-babel": "^4.4.0",
    "rollup-plugin-cleanup": "^3.2.1",
    "rollup-plugin-copy": "^3.4.0",
    "rollup-plugin-node-builtins": "^2.1.2",
    "rollup-plugin-peer-deps-external": "^2.2.4",
    "rollup-plugin-postcss": "^4.0.2",
    "rollup-plugin-terser": "^7.0.2",
    "rollup-plugin-vue": "5.1.9",
    "vue-template-compiler": "^2.7.0"
  },
  "dependencies": {
    "axios": "^0.27.2",
    "babel-eslint": "^10.1.0",
    "core-js": "^3.8.3",
    "vant": "^2.12.48",
    "vue": "^2.7.0",
    "vue-runtime-helpers": "^1.1.2"
  },
  "peerDependencies": {
    "vue": "^2.7.0"
  },
  "browserslist": [
    "defaults",
    "not ie < 8",
    "last 2 versions",
    "> 1%",
    "iOS 7",
    "last 3 iOS versions"
  ]
}
import fs from 'fs';
import path from 'path';
// import autoInstall from '@rollup/plugin-auto-install'; // 自动安装由包导入的依赖项,即使还没有在package.json
import json from '@rollup/plugin-json'; // 将json文件转换为esm模块
import vue from 'rollup-plugin-vue'; // Vue文件编译
import postcss from 'rollup-plugin-postcss'; // css、less、scss编译
import { terser } from 'rollup-plugin-terser'; // js压缩
import commonjs from '@rollup/plugin-commonjs'; // 将 CommonJS 模块转换为 ES6
import { nodeResolve } from '@rollup/plugin-node-resolve'; // 文件resolve,可省略/index.js等
import babel from '@rollup/plugin-babel'; // babel转译es6、es7=>es5
import peerDepsExternal from 'rollup-plugin-peer-deps-external'; // 设置打包外部引用的依赖,不混入
import autoprefixer from 'autoprefixer'; // css兼容,搭配package.json里browserslist使用
import cssnano from 'cssnano'; // 压缩css代码
// import image from '@rollup/plugin-image';  // 图片转base64,配置项未生效,改为@rollup/plugin-url
import url from '@rollup/plugin-url'; // 可以将文件导入为 data-URIs 或 ES Modules,比如复制图片
import copy from 'rollup-plugin-copy'; // 文件拷贝
import replace from '@rollup/plugin-replace'; // 打包时替换
import alias from '@rollup/plugin-alias'; // import alias
import builtins from 'rollup-plugin-node-builtins';
// import globals from 'rollup-plugin-node-globals';

const nodeEnv = process.env.NODE_ENV;
const isProd = process.env.NODE_ENV === 'production'; // 生产环境判断

// 公共插件配置
const plugins = [
  // globals(),
  builtins(),
  // autoInstall(),
  peerDepsExternal({
    // includeDependencies: !isProd, // speed up 排除Dependencies所有依赖
  }),
  json(),
  nodeResolve(),
  commonjs(),
  vue({
    // Dynamically inject css as a <style> tag
    css: false,
    // Explicitly convert template to render function
    compileTemplate: true
  }),
  postcss({
    // 把 css 插入到 style 中
    // inject: true,
    // 把 css 放到和js同一目录
    extensions: ['.css', '.less', 'scss'],
    extract: true,
    plugins: [autoprefixer(), isProd ? cssnano() : null]
  }),
  babel({
    // presets必须设置子这里,.babelrc文件里没生效
    presets: ['@babel/preset-env'],
    plugins: [
      ['import', {
        libraryName: 'vant',
        libraryDirectory: 'es',
        style: true
      }, 'vant']
    ],
    // babelHelpers: 'bundled',
    exclude: 'node_modules/**'
  }),
  // image({
  //   output: path.resolve(__dirname, 'lib'), // 打包后的文件
  //   extensions: /\.(png|jpg|jpeg|gif|svg)$/,
  //   limit: 1024 * 10, // 文件大小的限制(字节)。当一个文件没有超过限制时,它将被转换为 base64字符串,否则,它将被复制到output下
  //   exclude: 'node_modules/**',
  // }),
  url({
    destDir: `./lib/assets/images`,
    publicPath: '../assets/images/',
    limit: 1024 * 10 // 超过10kb复制,否则转base64
  }),
  alias({
    resolve: ['.js'],
    entries: [
      // { find: 'utils', replacement: '../../../utils' },
      { find: '@', replacement: './packages' }
    ]
  }),
  copy({
    targets: [
      // { src: 'src/index.html', dest: 'lib/public' },
      // {
      //   src: ['assets/fonts/arial.woff', 'assets/fonts/arial.woff2'],
      //   dest: 'lib/public/fonts',
      // },
      // { src: 'assets/images/**/*', dest: 'lib/public/images' },
    ]
  }),
  replace({
    preventAssignment: true,
    'process.env.NODE_ENV': JSON.stringify(nodeEnv)
  })
];

// 如果是生产环境,开启压缩
isProd && plugins.push(terser());

// packages 文件夹路径
const root = path.resolve(__dirname, 'packages');
module.exports = fs
  .readdirSync(root)
  // 过滤,只保留文件夹
  .filter((item) => fs.statSync(path.resolve(root, item)).isDirectory())
  // 为每一个文件夹创建对应的配置
  .map((item) => {
    // const pkg = require(path.resolve(root, item, 'package.json'));
    return {
      input: path.resolve(root, item, 'index.js'),
      output: [
        // {
        //   exports: 'auto',
        //   file: path.resolve(root, item, `../../lib/cjs/${item}.js`),
        //   format: 'cjs',
        // },
        {
          exports: 'auto',
          file: path.join(root, item, `../../lib/${item}/${item}-es.js`),
          format: 'es'
        },
        {
          exports: 'auto',
          file: path.join(root, item, `../../lib/${item}/index.js`),
          format: 'umd',
          name: item,
          globals: {
            vue: 'Vue' // 跟external 配套使用,指明global.Vue即是外部依赖vue
          }
        }
      ],
      plugins: plugins,
      // external: ['vue'], // 告诉rollup,不打包vue;将其视为外部依赖
      global: {
        jquery: '$', // 告诉rollup 全局变量$即是jquery
        vue: 'Vue' // 跟external 配套使用,指明global.Vue即是外部依赖vue
      }
    };
  });

参考文档

rollup官方地址:https://rollupjs.org/guide/zh/ rollup打包加速:http://www.redream.cn/2021/01/25/rollup%E6%89%93%E5%8C%85%E5%8A%A0%E9%80%9F/