chengdaohua-ui
v1.0.5
Published
hobby组件
Downloads
2
Readme
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
配置/使用
功能支持
- [x] 支持外链Vue和安装Vue
- [x] 支持全量引用和按需引用
- [x] 支持组件内按需引入第三方组件,例如Vant的van-button组件
- [x] 支持公共方法自动挂在到Vue.prototype下
- [x] 支持小图片(<10kb)自动转base64格式
- [x] 支持umd和es格式输出
- [x] 支持指定包(Vue,vant等)不编入UI库
- [x] 支持less、scss编译成css单独抽离打包
- [x] 支持组件库require引用外部包的方式
- [x] 支持alias定义,比如js引用路径通过@
- [x] 支持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可不写
优化
- 减少打包文件的数量
- 减少不必要的执行函数
- 增加打包缓存,进行增量打包
- 由单线程变为多线程
打包时排除外部包的引用
- 直接配置
external: ['vue'], // 告诉rollup,不打包vue;将其视为外部依赖
- 通过rollup-plugin-peer-deps-external插件排除
package.json里添加peerDependencies,添加打包时要排除的外部引用 设置includeDependencies,所有Dependencies都不会被打包
完整配置
{
"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/