├── js-modules ├── answer.js ├── out │ ├── cjs │ │ ├── run.js │ │ └── bundle.js │ ├── esm │ │ ├── bundle.js │ │ └── index.html │ ├── amd │ │ ├── bundle.js │ │ ├── index.html │ │ └── require.js │ ├── iife │ │ ├── bundle.js │ │ └── index.html │ ├── system │ │ ├── bundle-modified.js │ │ ├── index.html │ │ ├── named-register.js │ │ └── system.min.js │ └── umd │ │ ├── index.html │ │ ├── bundle.js │ │ └── require.js ├── index.js ├── package.json ├── rollup.config.js └── README.md ├── base-plugins ├── alias │ ├── a │ │ └── b │ │ │ └── answer.js │ ├── index.js │ ├── rollup-no-plugin.config.js │ └── rollup.config.js ├── commonjs │ ├── answer.js │ ├── index.js │ ├── out │ │ └── bundle.js │ ├── rollup-no-plugin.config.js │ └── rollup.config.js ├── node-resolve │ ├── answer │ │ └── index.js │ ├── index.js │ ├── out │ │ └── bundle.js │ ├── rollup-no-plugin.config.js │ └── rollup.config.js ├── multi-entry │ ├── a.js │ ├── b.js │ ├── rollup-no-plugin.config.js │ └── rollup.config.js ├── beep │ ├── index.js │ ├── rollup-no-plugin.config.js │ └── rollup.config.js ├── inject │ ├── index.js │ ├── rollup-no-plugin.config.js │ └── rollup.config.js ├── postcss │ ├── style.scss │ ├── index.js │ └── rollup.config.js ├── url │ ├── test.png │ ├── test02.png │ ├── index.js │ ├── rollup-no-plugin.config.js │ └── rollup.config.js ├── run │ ├── index.js │ └── rollup.config.js ├── strip │ ├── index.js │ ├── rollup-no-plugin.config.js │ └── rollup.config.js ├── html │ ├── index.js │ └── rollup.config.js ├── replace │ ├── index.js │ ├── rollup-no-plugin.config.js │ └── rollup.config.js ├── babel │ ├── index.js │ ├── rollup-no-plugin.config.js │ └── rollup.config.js ├── README.md ├── package.json └── blog.md ├── .gitignore └── README.md /js-modules/answer.js: -------------------------------------------------------------------------------- 1 | export default 42 -------------------------------------------------------------------------------- /base-plugins/alias/a/b/answer.js: -------------------------------------------------------------------------------- 1 | export default 42; -------------------------------------------------------------------------------- /base-plugins/commonjs/answer.js: -------------------------------------------------------------------------------- 1 | module.exports = 42 -------------------------------------------------------------------------------- /base-plugins/node-resolve/answer/index.js: -------------------------------------------------------------------------------- 1 | export default 42 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | **/node_modules 2 | 3 | **/out 4 | 5 | **/yarn.lock -------------------------------------------------------------------------------- /base-plugins/multi-entry/a.js: -------------------------------------------------------------------------------- 1 | export const printHello = () => { 2 | console.log('hello') 3 | } -------------------------------------------------------------------------------- /base-plugins/multi-entry/b.js: -------------------------------------------------------------------------------- 1 | export const printWorld = () => { 2 | console.log('world') 3 | } -------------------------------------------------------------------------------- /js-modules/out/cjs/run.js: -------------------------------------------------------------------------------- 1 | const Test = require('./bundle-by-lodash') 2 | 3 | Test.printAnswer() -------------------------------------------------------------------------------- /base-plugins/beep/index.js: -------------------------------------------------------------------------------- 1 | export const printAnswer = () => { 2 | await console.log(`answer is ${answer}`) 3 | } -------------------------------------------------------------------------------- /base-plugins/inject/index.js: -------------------------------------------------------------------------------- 1 | export const printAnswer = () => { 2 | console.log(_.includes([1,2,3], 1)) 3 | } -------------------------------------------------------------------------------- /base-plugins/postcss/style.scss: -------------------------------------------------------------------------------- 1 | .bg { 2 | color: red; 3 | 4 | .title { 5 | color: black; 6 | } 7 | } -------------------------------------------------------------------------------- /base-plugins/url/test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangshichun/rollup-demos/HEAD/base-plugins/url/test.png -------------------------------------------------------------------------------- /base-plugins/run/index.js: -------------------------------------------------------------------------------- 1 | const printAnswer = () => { 2 | console.log('hello world') 3 | } 4 | 5 | printAnswer() -------------------------------------------------------------------------------- /base-plugins/strip/index.js: -------------------------------------------------------------------------------- 1 | export const printAnswer = () => { 2 | console.log('hello, boy') 3 | return 42; 4 | } -------------------------------------------------------------------------------- /base-plugins/url/test02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhangshichun/rollup-demos/HEAD/base-plugins/url/test02.png -------------------------------------------------------------------------------- /base-plugins/html/index.js: -------------------------------------------------------------------------------- 1 | const printAnswer = () => { 2 | alert('hello world') 3 | } 4 | 5 | window.onload = printAnswer -------------------------------------------------------------------------------- /base-plugins/postcss/index.js: -------------------------------------------------------------------------------- 1 | import './style.scss' 2 | export const printAnswer = () => { 3 | console.log('answer is 42') 4 | } -------------------------------------------------------------------------------- /base-plugins/replace/index.js: -------------------------------------------------------------------------------- 1 | export const printAnswer = () => { 2 | console.log(`answer is 42`) 3 | } 4 | 5 | window.buildTime = "__build_time__"; -------------------------------------------------------------------------------- /base-plugins/alias/index.js: -------------------------------------------------------------------------------- 1 | import answer from "@/answer" 2 | 3 | export const printAnswer = async () => { 4 | console.log(`answer is ${answer}`) 5 | } 6 | -------------------------------------------------------------------------------- /base-plugins/commonjs/index.js: -------------------------------------------------------------------------------- 1 | import answer from "./answer"; 2 | 3 | export const printAnswer = () => { 4 | // 打印 5 | console.log(`the answer is ${answer}`) 6 | } -------------------------------------------------------------------------------- /base-plugins/node-resolve/index.js: -------------------------------------------------------------------------------- 1 | import answer from "./answer"; 2 | 3 | export const printAnswer = () => { 4 | // 打印 5 | console.log(`the answer is ${answer}`) 6 | } -------------------------------------------------------------------------------- /base-plugins/url/index.js: -------------------------------------------------------------------------------- 1 | import test01 from './test.png' 2 | import test02 from './test02.png' 3 | export const printAnswer = () => { 4 | console.log(`hello, ${test01}`) 5 | console.log(`hi, ${test02}`) 6 | } -------------------------------------------------------------------------------- /base-plugins/babel/index.js: -------------------------------------------------------------------------------- 1 | 2 | const sleep = (timestamp) => { 3 | return new Promise((resolve) => { 4 | setTimeout(() => { resolve() }, timestamp) 5 | }) 6 | } 7 | 8 | export const printAnswer = async () => { 9 | await sleep(3000) 10 | console.log('I am awake') 11 | } -------------------------------------------------------------------------------- /base-plugins/commonjs/out/bundle.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, '__esModule', { value: true }); 4 | 5 | var answer = 42; 6 | 7 | const printAnswer = () => { 8 | // 打印 9 | console.log(`the answer is ${answer}`); 10 | }; 11 | 12 | exports.printAnswer = printAnswer; 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rollup-demos 2 | 3 | ## 这个库是做什么的? 4 | 5 | 1. 是一个(将会)装满各种 `rollup` 小 `demo` 的库,用以验证关于 `rollup` 的各种小特性。 6 | 7 | 2. 是本人写技术 `blog` (公众号:`前端要摸鱼`) 的验证田 8 | 9 | ## demo list 10 | 11 | 1. [rollup构建产物验证demos](./js-modules/README.md) 12 | 13 | 2. [rollup常用插件验证demos](./base-plugins/README.md) 14 | -------------------------------------------------------------------------------- /base-plugins/node-resolve/out/bundle.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, '__esModule', { value: true }); 4 | 5 | var answer = 42; 6 | 7 | const printAnswer = () => { 8 | // 打印 9 | console.log(`the answer is ${answer}`); 10 | }; 11 | 12 | exports.printAnswer = printAnswer; 13 | -------------------------------------------------------------------------------- /js-modules/index.js: -------------------------------------------------------------------------------- 1 | import answer from "./answer"; 2 | import { repeat } from 'lodash' 3 | // 定义一个无用变量 4 | const unusedVar = 'May the 4th' 5 | 6 | export const printAnswer = () => { 7 | // 打印 8 | console.log(`the answer is ${answer}`) 9 | // 测试 lodash 的能力,打印42个1 10 | console.log(repeat('1', answer)) 11 | } -------------------------------------------------------------------------------- /js-modules/out/esm/bundle.js: -------------------------------------------------------------------------------- 1 | import repeat from '../../node_modules/lodash-es/repeat.js'; 2 | 3 | var answer = 42; 4 | 5 | const printAnswer = () => { 6 | // 打印 7 | console.log(`the answer is ${answer}`); 8 | // 测试 lodash 的能力,打印42个1 9 | console.log(repeat('1', answer)); 10 | }; 11 | 12 | export { printAnswer }; 13 | -------------------------------------------------------------------------------- /base-plugins/multi-entry/rollup-no-plugin.config.js: -------------------------------------------------------------------------------- 1 | // rollup.config.js 2 | import path from 'path' 3 | 4 | export default { 5 | // 核心选项 6 | input: [path.resolve(__dirname, './a.js'), path.resolve(__dirname, './b.js')], // 必须 7 | plugins: [ 8 | ], 9 | output: { 10 | dir: path.resolve(__dirname, 'out'), 11 | format: 'esm' 12 | }, 13 | }; -------------------------------------------------------------------------------- /base-plugins/replace/rollup-no-plugin.config.js: -------------------------------------------------------------------------------- 1 | // rollup.config.js 2 | import path from 'path' 3 | 4 | export default { 5 | // 核心选项 6 | input: path.resolve(__dirname, './index.js'), // 必须 7 | plugins: [], 8 | output: [ 9 | { 10 | file: path.resolve(__dirname, 'out/bundle-no-plugin.js'), 11 | format: 'esm' 12 | }, 13 | ] 14 | }; -------------------------------------------------------------------------------- /base-plugins/beep/rollup-no-plugin.config.js: -------------------------------------------------------------------------------- 1 | // rollup.config.js 2 | import path from 'path' 3 | 4 | export default { 5 | // 核心选项 6 | input: path.resolve(__dirname, './index.js'), // 必须 7 | plugins: [ 8 | ], 9 | output: [ 10 | { 11 | file: path.resolve(__dirname, 'out/bundle-no-plugin.js'), 12 | format: 'esm' 13 | }, 14 | ] 15 | }; -------------------------------------------------------------------------------- /base-plugins/url/rollup-no-plugin.config.js: -------------------------------------------------------------------------------- 1 | // rollup.config.js 2 | import path from 'path' 3 | 4 | export default { 5 | // 核心选项 6 | input: path.resolve(__dirname, './index.js'), // 必须 7 | plugins: [ 8 | ], 9 | output: [ 10 | { 11 | file: path.resolve(__dirname, 'out/bundle-no-plugin.js'), 12 | format: 'esm' 13 | }, 14 | ] 15 | }; -------------------------------------------------------------------------------- /base-plugins/strip/rollup-no-plugin.config.js: -------------------------------------------------------------------------------- 1 | // rollup.config.js 2 | import path from 'path' 3 | 4 | export default { 5 | // 核心选项 6 | input: path.resolve(__dirname, './index.js'), // 必须 7 | plugins: [ 8 | ], 9 | output: [ 10 | { 11 | file: path.resolve(__dirname, 'out/bundle-no-plugin.js'), 12 | format: 'esm' 13 | }, 14 | ] 15 | }; -------------------------------------------------------------------------------- /base-plugins/alias/rollup-no-plugin.config.js: -------------------------------------------------------------------------------- 1 | // rollup.config.js 2 | import path from 'path' 3 | 4 | export default { 5 | // 核心选项 6 | input: path.resolve(__dirname, './index.js'), // 必须 7 | plugins: [ 8 | ], 9 | output: [ 10 | { 11 | file: path.resolve(__dirname, 'out/bundle-no-plugin.js'), 12 | format: 'esm' 13 | }, 14 | ], 15 | external: ['lodash'] 16 | }; -------------------------------------------------------------------------------- /base-plugins/babel/rollup-no-plugin.config.js: -------------------------------------------------------------------------------- 1 | // rollup.config.js 2 | import path from 'path' 3 | 4 | export default { 5 | // 核心选项 6 | input: path.resolve(__dirname, './index.js'), // 必须 7 | plugins: [ 8 | ], 9 | output: [ 10 | { 11 | file: path.resolve(__dirname, 'out/bundle-no-plugin.js'), 12 | format: 'esm' 13 | }, 14 | ], 15 | external: ['lodash'] 16 | }; -------------------------------------------------------------------------------- /js-modules/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "js-modules", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "scripts": { 7 | "build": "rollup --config" 8 | }, 9 | "dependencies": { 10 | "jquery": "^3.6.0", 11 | "lodash": "^4.17.21", 12 | "lodash-es": "^4.17.21" 13 | }, 14 | "devDependencies": { 15 | "rollup": "^2.63.0" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /base-plugins/commonjs/rollup-no-plugin.config.js: -------------------------------------------------------------------------------- 1 | // rollup.config.js 2 | import path from 'path' 3 | 4 | export default { 5 | // 核心选项 6 | input: path.resolve(__dirname, './index.js'), // 必须 7 | plugins: [ 8 | ], 9 | output: [ 10 | { 11 | file: path.resolve(__dirname, 'out/bundle-no-plugin.js'), 12 | format: 'cjs' 13 | }, 14 | ], 15 | external: ['lodash'] 16 | }; -------------------------------------------------------------------------------- /base-plugins/inject/rollup-no-plugin.config.js: -------------------------------------------------------------------------------- 1 | // rollup.config.js 2 | import path from 'path' 3 | 4 | export default { 5 | // 核心选项 6 | input: path.resolve(__dirname, './index.js'), // 必须 7 | plugins: [ 8 | ], 9 | output: [ 10 | { 11 | file: path.resolve(__dirname, 'out/bundle-no-plugin.js'), 12 | format: 'esm' 13 | }, 14 | ], 15 | external: ['lodash'] 16 | }; -------------------------------------------------------------------------------- /base-plugins/node-resolve/rollup-no-plugin.config.js: -------------------------------------------------------------------------------- 1 | // rollup.config.js 2 | import path from 'path' 3 | 4 | export default { 5 | // 核心选项 6 | input: path.resolve(__dirname, './index.js'), // 必须 7 | plugins: [ 8 | ], 9 | output: [ 10 | { 11 | file: path.resolve(__dirname, 'out/bundle-no-plugin.js'), 12 | format: 'cjs' 13 | }, 14 | ], 15 | external: ['lodash'] 16 | }; -------------------------------------------------------------------------------- /base-plugins/url/rollup.config.js: -------------------------------------------------------------------------------- 1 | // rollup.config.js 2 | 3 | import url from '@rollup/plugin-url'; 4 | import path from 'path' 5 | 6 | 7 | export default { 8 | // 核心选项 9 | input: path.resolve(__dirname, './index.js'), // 必须 10 | plugins: [ 11 | url() 12 | ], 13 | output: [ 14 | { 15 | file: path.resolve(__dirname, 'out/bundle.js'), 16 | format: 'esm' 17 | }, 18 | ], 19 | }; -------------------------------------------------------------------------------- /js-modules/out/cjs/bundle.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, '__esModule', { value: true }); 4 | 5 | var lodash = require('lodash'); 6 | 7 | var answer = 42; 8 | 9 | const printAnswer = () => { 10 | // 打印 11 | console.log(`the answer is ${answer}`); 12 | // 测试 lodash 的能力,打印42个1 13 | console.log(lodash.repeat('1', answer)); 14 | }; 15 | 16 | exports.printAnswer = printAnswer; 17 | -------------------------------------------------------------------------------- /base-plugins/beep/rollup.config.js: -------------------------------------------------------------------------------- 1 | // rollup.config.js 2 | 3 | import beep from '@rollup/plugin-beep'; 4 | import path from 'path' 5 | 6 | 7 | export default { 8 | // 核心选项 9 | input: path.resolve(__dirname, './index.js'), // 必须 10 | plugins: [ 11 | beep() 12 | ], 13 | output: [ 14 | { 15 | file: path.resolve(__dirname, 'out/bundle.js'), 16 | format: 'esm' 17 | }, 18 | ], 19 | }; -------------------------------------------------------------------------------- /base-plugins/run/rollup.config.js: -------------------------------------------------------------------------------- 1 | // rollup.config.js 2 | 3 | import run from '@rollup/plugin-run'; 4 | import path from 'path' 5 | 6 | 7 | export default { 8 | // 核心选项 9 | input: path.resolve(__dirname, './index.js'), // 必须 10 | plugins: [ 11 | run(), 12 | ], 13 | output: [ 14 | { 15 | file: path.resolve(__dirname, 'out/bundle.js'), 16 | format: 'esm' 17 | }, 18 | ], 19 | }; -------------------------------------------------------------------------------- /base-plugins/commonjs/rollup.config.js: -------------------------------------------------------------------------------- 1 | // rollup.config.js 2 | import commonjs from '@rollup/plugin-commonjs' 3 | import path from 'path' 4 | 5 | export default { 6 | // 核心选项 7 | input: path.resolve(__dirname, './index.js'), // 必须 8 | plugins: [ 9 | commonjs() 10 | ], 11 | output: [ 12 | { 13 | file: path.resolve(__dirname, 'out/bundle.js'), 14 | format: 'cjs' 15 | }, 16 | ], 17 | }; -------------------------------------------------------------------------------- /base-plugins/html/rollup.config.js: -------------------------------------------------------------------------------- 1 | // rollup.config.js 2 | 3 | import html from '@rollup/plugin-html'; 4 | import path from 'path' 5 | 6 | 7 | export default { 8 | // 核心选项 9 | input: path.resolve(__dirname, './index.js'), // 必须 10 | plugins: [ 11 | html({}) 12 | ], 13 | output: [ 14 | { 15 | file: path.resolve(__dirname, 'out/bundle.js'), 16 | format: 'esm' 17 | }, 18 | ], 19 | }; -------------------------------------------------------------------------------- /base-plugins/multi-entry/rollup.config.js: -------------------------------------------------------------------------------- 1 | // rollup.config.js 2 | 3 | import multi from '@rollup/plugin-multi-entry'; 4 | import path from 'path' 5 | 6 | 7 | export default { 8 | // 核心选项 9 | input: [path.resolve(__dirname, 'a.js'), path.resolve(__dirname, 'b.js')], // 必须 10 | plugins: [ 11 | multi() 12 | ], 13 | output: { 14 | dir: path.resolve(__dirname, 'out'), 15 | format: 'esm' 16 | }, 17 | }; -------------------------------------------------------------------------------- /base-plugins/node-resolve/rollup.config.js: -------------------------------------------------------------------------------- 1 | // rollup.config.js 2 | import { nodeResolve } from '@rollup/plugin-node-resolve' 3 | import path from 'path' 4 | 5 | export default { 6 | // 核心选项 7 | input: path.resolve(__dirname, './index.js'), // 必须 8 | plugins: [ 9 | nodeResolve() 10 | ], 11 | output: [ 12 | { 13 | file: path.resolve(__dirname, 'out/bundle.js'), 14 | format: 'cjs' 15 | }, 16 | ], 17 | }; -------------------------------------------------------------------------------- /js-modules/out/esm/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /base-plugins/babel/rollup.config.js: -------------------------------------------------------------------------------- 1 | // rollup.config.js 2 | import babel from '@rollup/plugin-babel';import path from 'path' 3 | 4 | export default { 5 | // 核心选项 6 | input: path.resolve(__dirname, './index.js'), // 必须 7 | plugins: [ 8 | babel({ 9 | presets: ['@babel/preset-env'] 10 | }) 11 | ], 12 | output: [ 13 | { 14 | file: path.resolve(__dirname, 'out/bundle.js'), 15 | format: 'esm' 16 | }, 17 | ], 18 | }; -------------------------------------------------------------------------------- /base-plugins/strip/rollup.config.js: -------------------------------------------------------------------------------- 1 | // rollup.config.js 2 | 3 | import strip from '@rollup/plugin-strip'; 4 | import path from 'path' 5 | 6 | 7 | export default { 8 | // 核心选项 9 | input: path.resolve(__dirname, './index.js'), // 必须 10 | plugins: [ 11 | strip({ 12 | functions: ['console.*'] 13 | }) 14 | ], 15 | output: [ 16 | { 17 | file: path.resolve(__dirname, 'out/bundle.js'), 18 | format: 'esm' 19 | }, 20 | ], 21 | }; -------------------------------------------------------------------------------- /js-modules/out/amd/bundle.js: -------------------------------------------------------------------------------- 1 | define('Test', ['exports', 'lodash'], (function (exports, lodash) { 'use strict'; 2 | 3 | var answer = 42; 4 | 5 | const printAnswer = () => { 6 | // 打印 7 | console.log(`the answer is ${answer}`); 8 | // 测试 lodash 的能力,打印42个1 9 | console.log(lodash.repeat('1', answer)); 10 | }; 11 | 12 | exports.printAnswer = printAnswer; 13 | 14 | Object.defineProperty(exports, '__esModule', { value: true }); 15 | 16 | })); 17 | -------------------------------------------------------------------------------- /js-modules/out/iife/bundle.js: -------------------------------------------------------------------------------- 1 | var Test = (function (exports, lodash) { 2 | 'use strict'; 3 | 4 | var answer = 42; 5 | 6 | const printAnswer = () => { 7 | // 打印 8 | console.log(`the answer is ${answer}`); 9 | // 测试 lodash 的能力,打印42个1 10 | console.log(lodash.repeat('1', answer)); 11 | }; 12 | 13 | exports.printAnswer = printAnswer; 14 | 15 | Object.defineProperty(exports, '__esModule', { value: true }); 16 | 17 | return exports; 18 | 19 | })({}, lodash); 20 | -------------------------------------------------------------------------------- /base-plugins/inject/rollup.config.js: -------------------------------------------------------------------------------- 1 | // rollup.config.js 2 | 3 | import inject from '@rollup/plugin-inject'; 4 | import path from 'path' 5 | 6 | 7 | export default { 8 | // 核心选项 9 | input: path.resolve(__dirname, './index.js'), // 必须 10 | plugins: [ 11 | inject({ 12 | _: 'lodash', 13 | jquery: "jquery" 14 | }) 15 | ], 16 | output: [ 17 | { 18 | file: path.resolve(__dirname, 'out/bundle.js'), 19 | format: 'esm' 20 | }, 21 | ], 22 | external: ['lodash', 'jquery'] 23 | }; -------------------------------------------------------------------------------- /base-plugins/alias/rollup.config.js: -------------------------------------------------------------------------------- 1 | // rollup.config.js 2 | import alias from '@rollup/plugin-alias'; 3 | import path from 'path' 4 | 5 | export default { 6 | // 核心选项 7 | input: path.resolve(__dirname, './index.js'), // 必须 8 | plugins: [ 9 | alias({ 10 | entries: [ 11 | { find: '@', replacement: path.resolve(__dirname, './a/b') }, 12 | ] 13 | }) 14 | ], 15 | output: [ 16 | { 17 | file: path.resolve(__dirname, 'out/bundle.js'), 18 | format: 'esm' 19 | }, 20 | ], 21 | }; -------------------------------------------------------------------------------- /base-plugins/postcss/rollup.config.js: -------------------------------------------------------------------------------- 1 | // rollup.config.js 2 | 3 | import postcss from 'rollup-plugin-postcss'; 4 | import path from 'path' 5 | 6 | export default { 7 | // 核心选项 8 | input: path.resolve(__dirname, './index.js'), // 必须 9 | plugins: [ 10 | postcss({ 11 | plugins: [ 12 | ], 13 | extract: true, 14 | use: ["sass"], 15 | writeDefinitions: true 16 | }) 17 | ], 18 | output: [ 19 | { 20 | file: path.resolve(__dirname, 'out/bundle.js'), 21 | format: 'esm' 22 | }, 23 | ], 24 | }; -------------------------------------------------------------------------------- /base-plugins/replace/rollup.config.js: -------------------------------------------------------------------------------- 1 | // rollup.config.js 2 | 3 | import replace from '@rollup/plugin-replace'; 4 | import path from 'path' 5 | import dayjs from 'dayjs' 6 | 7 | export default { 8 | // 核心选项 9 | input: path.resolve(__dirname, './index.js'), // 必须 10 | plugins: [ 11 | replace({ 12 | __build_time__: dayjs().format('YYYY-MM-DD HH:mm:ss'), 13 | preventAssignment: true 14 | }) 15 | ], 16 | output: [ 17 | { 18 | file: path.resolve(__dirname, 'out/bundle.js'), 19 | format: 'esm' 20 | }, 21 | ], 22 | }; -------------------------------------------------------------------------------- /js-modules/out/iife/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | -------------------------------------------------------------------------------- /js-modules/out/system/bundle-modified.js: -------------------------------------------------------------------------------- 1 | System.register('Test', ['https://unpkg.com/lodash@4.17.21/lodash.js'], (function (exports) { 2 | 'use strict'; 3 | var repeat; 4 | return { 5 | setters: [function (module) { 6 | repeat = window._.repeat; 7 | }], 8 | execute: (function () { 9 | 10 | var answer = 42; 11 | 12 | const printAnswer = exports('printAnswer', () => { 13 | // 打印 14 | console.log(`the answer is ${answer}`); 15 | // 测试 lodash 的能力,打印42个1 16 | console.log(repeat('1', answer)); 17 | }); 18 | 19 | }) 20 | }; 21 | })); 22 | -------------------------------------------------------------------------------- /js-modules/out/system/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 10 | 11 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /js-modules/out/umd/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 16 | 17 | 18 | 19 | 27 | 28 | -------------------------------------------------------------------------------- /js-modules/out/amd/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Document 8 | 9 | 16 | 17 | 18 | 19 | 27 | 28 | -------------------------------------------------------------------------------- /js-modules/out/umd/bundle.js: -------------------------------------------------------------------------------- 1 | (function (global, factory) { 2 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('lodash')) : 3 | typeof define === 'function' && define.amd ? define('Test', ['exports', 'lodash'], factory) : 4 | (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.Test = {}, global.lodash)); 5 | })(this, (function (exports, lodash) { 'use strict'; 6 | 7 | var answer = 42; 8 | 9 | const printAnswer = () => { 10 | // 打印 11 | console.log(`the answer is ${answer}`); 12 | // 测试 lodash 的能力,打印42个1 13 | console.log(lodash.repeat('1', answer)); 14 | }; 15 | 16 | exports.printAnswer = printAnswer; 17 | 18 | Object.defineProperty(exports, '__esModule', { value: true }); 19 | 20 | })); 21 | -------------------------------------------------------------------------------- /base-plugins/README.md: -------------------------------------------------------------------------------- 1 | # base-plugins 2 | 3 | ## 使用法门 4 | 5 | ### 安装 6 | 7 | ```bash 8 | yarn # or npm install 9 | ``` 10 | 11 | ### 执行脚本 12 | 13 | 可以通过执行以下脚本,一一印证插件的作用。具体详情,可参考本文:[地址](./blog.md) 14 | 15 | - build-commonjs 16 | - build-commonjs-no-plugin 17 | - build-node-resolve 18 | - build-node-resolve-no-plugin 19 | - build-babel 20 | - build-babel-no-plugin 21 | - build-alias 22 | - build-alias-no-plugin 23 | - build-beep 24 | - build-beep-no-plugin 25 | - build-data-uri 26 | - build-data-uri-no-plugin 27 | - build-html 28 | - build-inject 29 | - build-inject-no-plugin 30 | - build-multi-entry 31 | - build-multi-entry-no-plugin 32 | - build-replace 33 | - build-replace-no-plugin 34 | - build-run 35 | - build-strip 36 | - build-strip-no-plugin 37 | - build-url 38 | - build-url-no-plugin 39 | - build-postcss 40 | -------------------------------------------------------------------------------- /js-modules/rollup.config.js: -------------------------------------------------------------------------------- 1 | // rollup.config.js 2 | export default { 3 | // 核心选项 4 | input: 'index.js', // 必须 5 | plugins: [], 6 | output: [ 7 | { 8 | file: 'out/amd/bundle.js', 9 | format: 'amd', 10 | amd: { 11 | id: 'Test' 12 | } 13 | }, 14 | { 15 | file: 'out/cjs/bundle.js', 16 | format: 'cjs' 17 | }, 18 | { 19 | file: 'out/esm/bundle.js', 20 | format: 'esm' 21 | }, 22 | { 23 | file: 'out/iife/bundle.js', 24 | format: 'iife', 25 | name: 'Test', 26 | globals: { 27 | lodash: 'lodash' 28 | } 29 | }, 30 | { 31 | file: 'out/umd/bundle.js', 32 | format: 'umd', 33 | name: 'Test', 34 | globals: { 35 | lodash: 'lodash' 36 | }, 37 | amd: { 38 | id: 'Test' 39 | } 40 | }, 41 | { 42 | file: 'out/system/bundle.js', 43 | format: 'system' 44 | } 45 | ], 46 | external: ['lodash'] 47 | }; -------------------------------------------------------------------------------- /js-modules/out/system/named-register.js: -------------------------------------------------------------------------------- 1 | (function(){/* 2 | * SystemJS named register extension 3 | * Supports System.register('name', [..deps..], function (_export, _context) { ... }) 4 | * 5 | * Names are written to the registry as-is 6 | * System.register('x', ...) can be imported as System.import('x') 7 | */ 8 | (function (global) { 9 | var System = global.System; 10 | setRegisterRegistry(System); 11 | var systemJSPrototype = System.constructor.prototype; 12 | var constructor = System.constructor; 13 | var SystemJS = function () { 14 | constructor.call(this); 15 | setRegisterRegistry(this); 16 | }; 17 | SystemJS.prototype = systemJSPrototype; 18 | System.constructor = SystemJS; 19 | 20 | var firstNamedDefine, firstName; 21 | 22 | function setRegisterRegistry(systemInstance) { 23 | systemInstance.registerRegistry = Object.create(null); 24 | systemInstance.namedRegisterAliases = Object.create(null); 25 | } 26 | 27 | var register = systemJSPrototype.register; 28 | systemJSPrototype.register = function (name, deps, declare) { 29 | if (typeof name !== 'string') 30 | return register.apply(this, arguments); 31 | var define = [deps, declare]; 32 | this.registerRegistry[name] = define; 33 | if (!firstNamedDefine) { 34 | firstNamedDefine = define; 35 | firstName = name; 36 | } 37 | Promise.resolve().then(function () { 38 | firstNamedDefine = null; 39 | firstName = null; 40 | }); 41 | return register.apply(this, [deps, declare]); 42 | }; 43 | 44 | var resolve = systemJSPrototype.resolve; 45 | systemJSPrototype.resolve = function (id, parentURL) { 46 | try { 47 | // Prefer import map (or other existing) resolution over the registerRegistry 48 | return resolve.call(this, id, parentURL); 49 | } catch (err) { 50 | if (id in this.registerRegistry) { 51 | return this.namedRegisterAliases[id] || id; 52 | } 53 | throw err; 54 | } 55 | }; 56 | 57 | var instantiate = systemJSPrototype.instantiate; 58 | systemJSPrototype.instantiate = function (url, firstParentUrl) { 59 | var result = this.registerRegistry[url]; 60 | if (result) { 61 | this.registerRegistry[url] = null; 62 | return result; 63 | } else { 64 | return instantiate.call(this, url, firstParentUrl); 65 | } 66 | }; 67 | 68 | var getRegister = systemJSPrototype.getRegister; 69 | systemJSPrototype.getRegister = function (url) { 70 | // Calling getRegister() because other extras need to know it was called so they can perform side effects 71 | var register = getRegister.call(this, url); 72 | 73 | if (firstName && url) { 74 | this.namedRegisterAliases[firstName] = url; 75 | } 76 | var result = firstNamedDefine || register; 77 | firstNamedDefine = null; 78 | firstName = null; 79 | return result; 80 | }; 81 | })(typeof self !== 'undefined' ? self : global);}()); -------------------------------------------------------------------------------- /base-plugins/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "js-modules", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "scripts": { 7 | "build-commonjs": "rollup --config ./commonjs/rollup.config.js", 8 | "build-commonjs-no-plugin": "rollup --config ./commonjs/rollup-no-plugin.config.js", 9 | "build-node-resolve": "rollup --config ./node-resolve/rollup.config.js", 10 | "build-node-resolve-no-plugin": "rollup --config ./node-resolve/rollup-no-plugin.config.js", 11 | "build-babel": "rollup --config ./babel/rollup.config.js", 12 | "build-babel-no-plugin": "rollup --config ./babel/rollup-no-plugin.config.js", 13 | "build-alias": "rollup --config ./alias/rollup.config.js", 14 | "build-alias-no-plugin": "rollup --config ./alias/rollup-no-plugin.config.js", 15 | "build-beep": "rollup --config ./beep/rollup.config.js", 16 | "build-beep-no-plugin": "rollup --config ./beep/rollup-no-plugin.config.js", 17 | "build-data-uri": "rollup --config ./data-uri/rollup.config.js", 18 | "build-data-uri-no-plugin": "rollup --config ./data-uri/rollup-no-plugin.config.js", 19 | "build-html": "rollup --config ./html/rollup.config.js", 20 | "build-inject": "rollup --config ./inject/rollup.config.js", 21 | "build-inject-no-plugin": "rollup --config ./inject/rollup-no-plugin.config.js", 22 | "build-multi-entry": "rollup --config ./multi-entry/rollup.config.js", 23 | "build-multi-entry-no-plugin": "rollup --config ./multi-entry/rollup-no-plugin.config.js", 24 | "build-replace": "rollup --config ./replace/rollup.config.js", 25 | "build-replace-no-plugin": "rollup --config ./replace/rollup-no-plugin.config.js", 26 | "build-run": "rollup --config ./run/rollup.config.js", 27 | "build-strip": "rollup --config ./strip/rollup.config.js", 28 | "build-strip-no-plugin": "rollup --config ./strip/rollup-no-plugin.config.js", 29 | "build-url": "rollup --config ./url/rollup.config.js", 30 | "build-url-no-plugin": "rollup --config ./url/rollup-no-plugin.config.js", 31 | "build-postcss": "rollup --config ./postcss/rollup.config.js" 32 | }, 33 | "dependencies": { 34 | "jquery": "^3.6.0", 35 | "lodash": "^4.17.21", 36 | "lodash-es": "^4.17.21" 37 | }, 38 | "devDependencies": { 39 | "dayjs": "^1.10.7", 40 | "@babel/core": "^7.17.5", 41 | "@babel/preset-env": "^7.16.11", 42 | "rollup": "^2.63.0", 43 | "http-server": "^14.1.0", 44 | "@rollup/plugin-commonjs": "^21.0.1", 45 | "@rollup/plugin-node-resolve": "^13.1.3", 46 | "@rollup/plugin-babel": "^5.3.0", 47 | "@rollup/plugin-alias": "^3.1.9", 48 | "@rollup/plugin-beep": "0.2.0", 49 | "@rollup/plugin-data-uri": "^0.1.1", 50 | "@rollup/plugin-html": "^0.2.4", 51 | "@rollup/plugin-inject": "^4.0.4", 52 | "@rollup/plugin-multi-entry": "^4.1.0", 53 | "@rollup/plugin-replace": "^3.1.0", 54 | "@rollup/plugin-run": "^2.1.0", 55 | "@rollup/plugin-strip": "^2.1.0", 56 | "@rollup/plugin-url": "^6.1.0", 57 | "rollup-plugin-postcss": "^4.0.2", 58 | "postcss": "^8.4.6", 59 | "sass": "^1.49.8" 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /js-modules/out/system/system.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * SystemJS 6.11.0 3 | */ 4 | !function(){function e(e,t){return(t||"")+" (SystemJS Error#"+e+" https://git.io/JvFET#"+e+")"}function t(e,t){if(-1!==e.indexOf("\\")&&(e=e.replace(/\\/g,"/")),"/"===e[0]&&"/"===e[1])return t.slice(0,t.indexOf(":")+1)+e;if("."===e[0]&&("/"===e[1]||"."===e[1]&&("/"===e[2]||2===e.length&&(e+="/"))||1===e.length&&(e+="/"))||"/"===e[0]){var n,r=t.slice(0,t.indexOf(":")+1);if(n="/"===t[r.length+1]?"file:"!==r?(n=t.slice(r.length+2)).slice(n.indexOf("/")+1):t.slice(8):t.slice(r.length+("/"===t[r.length])),"/"===e[0])return t.slice(0,t.length-n.length-1)+e;for(var i=n.slice(0,n.lastIndexOf("/")+1)+e,o=[],s=-1,u=0;i.length>u;u++)-1!==s?"/"===i[u]&&(o.push(i.slice(s,u+1)),s=-1):"."===i[u]?"."!==i[u+1]||"/"!==i[u+2]&&u+2!==i.length?"/"===i[u+1]||u+1===i.length?u+=1:s=u:(o.pop(),u+=2):s=u;return-1!==s&&o.push(i.slice(s)),t.slice(0,t.length-n.length)+o.join("")}}function n(e,n){return t(e,n)||(-1!==e.indexOf(":")?e:t("./"+e,n))}function r(e,n,r,i,o){for(var c in e){var a=t(c,r)||c,f=e[c];if("string"==typeof f){var l=u(i,t(f,r)||f,o);l?n[a]=l:s("W1",c,f,"bare specifier did not resolve")}}}function i(e,t){if(t[e])return e;var n=e.length;do{var r=e.slice(0,n+1);if(r in t)return r}while(-1!==(n=e.lastIndexOf("/",n-1)))}function o(e,t){var n=i(e,t);if(n){var r=t[n];if(null===r)return;if(n.length>=e.length||"/"===r[r.length-1])return r+e.slice(n.length);s("W2",n,r,"should have a trailing '/'")}}function s(t,n,r,i){console.warn(e(t,"Package target "+i+", resolving target '"+r+"' for "+n))}function u(e,t,n){for(var r=e.scopes,s=n&&i(n,r);s;){var u=o(t,r[s]);if(u)return u;s=i(s.slice(0,s.lastIndexOf("/")),r)}return o(t,e.imports)||-1!==t.indexOf(":")&&t}function c(){this[E]={}}function a(e){return e.id}function f(e,t,n,r){if(e.onload(n,t.id,t.d&&t.d.map(a),!!r),n)throw n}function l(t,n,r){var i=t[E][n];if(i)return i;var o=[],s=Object.create(null);b&&Object.defineProperty(s,b,{value:"Module"});var u=Promise.resolve().then((function(){return t.instantiate(n,r)})).then((function(r){if(!r)throw Error(e(2,"Module "+n+" did not instantiate"));var u=r[1]((function(e,t){i.h=!0;var n=!1;if("string"==typeof e)e in s&&s[e]===t||(s[e]=t,n=!0);else{for(var r in e)t=e[r],r in s&&s[r]===t||(s[r]=t,n=!0);e&&e.__esModule&&(s.__esModule=e.__esModule)}if(n)for(var u=0;o.length>u;u++){var c=o[u];c&&c(s)}return t}),2===r[1].length?{import:function(e){return t.import(e,n)},meta:t.createContext(n)}:void 0);return i.e=u.execute||function(){},[r[0],u.setters||[]]}),(function(e){throw i.e=null,i.er=e,f(t,i,e,!0),e})),c=u.then((function(e){return Promise.all(e[0].map((function(r,i){var o=e[1][i];return Promise.resolve(t.resolve(r,n)).then((function(e){var r=l(t,e,n);return Promise.resolve(r.I).then((function(){return o&&(r.i.push(o),!r.h&&r.I||o(r.n)),r}))}))}))).then((function(e){i.d=e}))}));return i=t[E][n]={id:n,i:o,n:s,I:u,L:c,h:!1,d:void 0,e:void 0,er:void 0,E:void 0,C:void 0,p:void 0}}function d(){[].forEach.call(document.querySelectorAll("script"),(function(t){if(!t.sp)if("systemjs-module"===t.type){if(t.sp=!0,!t.src)return;System.import("import:"===t.src.slice(0,7)?t.src.slice(7):n(t.src,h)).catch((function(e){if(e.message.indexOf("https://git.io/JvFET#3")>-1){var n=document.createEvent("Event");n.initEvent("error",!1,!1),t.dispatchEvent(n)}return Promise.reject(e)}))}else if("systemjs-importmap"===t.type){t.sp=!0;var i=t.src?fetch(t.src,{integrity:t.integrity}).then((function(e){if(!e.ok)throw Error("Invalid status code: "+e.status);return e.text()})).catch((function(n){return n.message=e("W4","Error fetching systemjs-import map "+t.src)+"\n"+n.message,console.warn(n),"function"==typeof t.onerror&&t.onerror(),"{}"})):t.innerHTML;M=M.then((function(){return i})).then((function(i){!function(t,i,o){var s={};try{s=JSON.parse(i)}catch(u){console.warn(Error(e("W5","systemjs-importmap contains invalid JSON")+"\n\n"+i+"\n"))}!function(e,t,i){var o;for(o in e.imports&&r(e.imports,i.imports,t,i,null),e.scopes||{}){var s=n(o,t);r(e.scopes[o],i.scopes[s]||(i.scopes[s]={}),t,i,s)}for(o in e.depcache||{})i.depcache[n(o,t)]=e.depcache[o];for(o in e.integrity||{})i.integrity[n(o,t)]=e.integrity[o]}(s,o,t)}(L,i,t.src||h)}))}}))}var h,v="undefined"!=typeof Symbol,p="undefined"!=typeof self,m="undefined"!=typeof document,g=p?self:global;if(m){var y=document.querySelector("base[href]");y&&(h=y.href)}if(!h&&"undefined"!=typeof location){var w=(h=location.href.split("#")[0].split("?")[0]).lastIndexOf("/");-1!==w&&(h=h.slice(0,w+1))}var S,b=v&&Symbol.toStringTag,E=v?Symbol():"@",O=c.prototype;O.import=function(e,t){var n=this;return Promise.resolve(n.prepareImport()).then((function(){return n.resolve(e,t)})).then((function(e){var t=l(n,e);return t.C||function(e,t){return t.C=function e(t,n,r,i){if(!i[n.id])return i[n.id]=!0,Promise.resolve(n.L).then((function(){return n.p&&null!==n.p.e||(n.p=r),Promise.all(n.d.map((function(n){return e(t,n,r,i)})))})).catch((function(e){if(n.er)throw e;throw n.e=null,f(t,n,e,!1),e}))}(e,t,t,{}).then((function(){return function e(t,n,r){function i(){try{var e=n.e.call(x);if(e)return e=e.then((function(){n.C=n.n,n.E=null,f(t,n,null,!0)}),(function(e){throw n.er=e,n.E=null,f(t,n,e,!0),e})),n.E=e;n.C=n.n,n.L=n.I=void 0}catch(r){throw n.er=r,r}finally{n.e=null,f(t,n,n.er,!0)}}if(!r[n.id]){if(r[n.id]=!0,!n.e){if(n.er)throw n.er;return n.E?n.E:void 0}var o;return n.d.forEach((function(i){try{var s=e(t,i,r);s&&(o=o||[]).push(s)}catch(u){throw n.e=null,n.er=u,f(t,n,u,!1),u}})),o?Promise.all(o).then(i):i()}}(e,t,{})})).then((function(){return t.n}))}(n,t)}))},O.createContext=function(e){var t=this;return{url:e,resolve:function(n,r){return Promise.resolve(t.resolve(n,r||e))}}},O.onload=function(){},O.register=function(e,t){S=[e,t]},O.getRegister=function(){var e=S;return S=void 0,e};var x=Object.freeze(Object.create(null));g.System=new c;var j,P,M=Promise.resolve(),L={imports:{},scopes:{},depcache:{},integrity:{}},C=m;if(O.prepareImport=function(e){return(C||e)&&(d(),C=!1),M},m&&(d(),window.addEventListener("DOMContentLoaded",d)),m){window.addEventListener("error",(function(e){I=e.filename,W=e.error}));var R=location.origin}O.createScript=function(e){var t=document.createElement("script");t.async=!0,e.indexOf(R+"/")&&(t.crossOrigin="anonymous");var n=L.integrity[e];return n&&(t.integrity=n),t.src=e,t};var I,W,T={},A=O.register;O.register=function(e,t){if(m&&"loading"===document.readyState&&"string"!=typeof e){var n=document.querySelectorAll("script[src]"),r=n[n.length-1];if(r){j=e;var i=this;P=setTimeout((function(){T[r.src]=[e,t],i.import(r.src)}))}}else j=void 0;return A.call(this,e,t)},O.instantiate=function(t,n){var r=T[t];if(r)return delete T[t],r;var i=this;return Promise.resolve(O.createScript(t)).then((function(r){return new Promise((function(o,s){r.addEventListener("error",(function(){s(Error(e(3,"Error loading "+t+(n?" from "+n:""))))})),r.addEventListener("load",(function(){if(document.head.removeChild(r),I===t)s(W);else{var e=i.getRegister(t);e&&e[0]===j&&clearTimeout(P),o(e)}})),document.head.appendChild(r)}))}))},O.shouldFetch=function(){return!1},"undefined"!=typeof fetch&&(O.fetch=fetch);var J=O.instantiate,N=/^(text|application)\/(x-)?javascript(;|$)/;O.instantiate=function(t,n){var r=this;return this.shouldFetch(t)?this.fetch(t,{credentials:"same-origin",integrity:L.integrity[t]}).then((function(i){if(!i.ok)throw Error(e(7,i.status+" "+i.statusText+", loading "+t+(n?" from "+n:"")));var o=i.headers.get("content-type");if(!o||!N.test(o))throw Error(e(4,'Unknown Content-Type "'+o+'", loading '+t+(n?" from "+n:"")));return i.text().then((function(e){return 0>e.indexOf("//# sourceURL=")&&(e+="\n//# sourceURL="+t),(0,eval)(e),r.getRegister(t)}))})):J.apply(this,arguments)},O.resolve=function(n,r){return u(L,t(n,r=r||h)||n,r)||function(t,n){throw Error(e(8,"Unable to resolve bare specifier '"+t+(n?"' from "+n:"'")))}(n,r)};var _=O.instantiate;O.instantiate=function(e,t){var n=L.depcache[e];if(n)for(var r=0;n.length>r;r++)l(this,this.resolve(n[r],e),e);return _.call(this,e,t)},p&&"function"==typeof importScripts&&(O.instantiate=function(e){var t=this;return Promise.resolve().then((function(){return importScripts(e),t.getRegister(e)}))}),function(e){function t(t){return!e.hasOwnProperty(t)||!isNaN(t)&&e.length>t||a&&e[t]&&"undefined"!=typeof window&&e[t].parent===window}var n,r,i,o=e.System.constructor.prototype,s=o.import;o.import=function(o,u){return function(){for(var o in n=r=void 0,e)t(o)||(n?r||(r=o):n=o,i=o)}(),s.call(this,o,u)};var u=[[],function(){return{}}],c=o.getRegister;o.getRegister=function(){var o=c.call(this);if(o)return o;var s,a=function(o){var s,u,c=0;for(var a in e)if(!t(a)){if(0===c&&a!==n||1===c&&a!==r)return a;s?(i=a,u=o&&u||a):s=a===i,c++}return u}(this.firstGlobalProp);if(!a)return u;try{s=e[a]}catch(f){return u}return[[],function(e){return{execute:function(){e(s),e({default:s,__useDefault:!0})}}}]};var a="undefined"!=typeof navigator&&-1!==navigator.userAgent.indexOf("Trident")}("undefined"!=typeof self?self:global),function(e){var t=e.System.constructor.prototype,r=/^[^#?]+\.(css|html|json|wasm)([?#].*)?$/;t.shouldFetch=function(e){return r.test(e)};var i=/^application\/json(;|$)/,o=/^text\/css(;|$)/,s=/^application\/wasm(;|$)/,u=t.fetch;t.fetch=function(t,r){return u(t,r).then((function(r){if(!r.ok)return r;var u=r.headers.get("content-type");return i.test(u)?r.json().then((function(e){return new Response(new Blob(['System.register([],function(e){return{execute:function(){e("default",'+JSON.stringify(e)+")}}})"],{type:"application/javascript"}))})):o.test(u)?r.text().then((function(e){return e=e.replace(/url\(\s*(?:(["'])((?:\\.|[^\n\\"'])+)\1|((?:\\.|[^\s,"'()\\])+))\s*\)/g,(function(e,r,i,o){return"url("+r+n(i||o,t)+r+")"})),new Response(new Blob(["System.register([],function(e){return{execute:function(){var s=new CSSStyleSheet();s.replaceSync("+JSON.stringify(e)+');e("default",s)}}})'],{type:"application/javascript"}))})):s.test(u)?(WebAssembly.compileStreaming?WebAssembly.compileStreaming(r):r.arrayBuffer().then(WebAssembly.compile)).then((function(n){e.System.wasmModules||(e.System.wasmModules=Object.create(null)),e.System.wasmModules[t]=n;var r=[],i=[];return WebAssembly.Module.imports&&WebAssembly.Module.imports(n).forEach((function(e){var t=JSON.stringify(e.module);-1===r.indexOf(t)&&(r.push(t),i.push("function(m){i["+t+"]=m}"))})),new Response(new Blob(["System.register(["+r.join(",")+"],function(e){var i={};return{setters:["+i.join(",")+"],execute:function(){return WebAssembly.instantiate(System.wasmModules["+JSON.stringify(t)+"],i).then(function(m){e(m.exports)})}}})"],{type:"application/javascript"}))})):r}))}}("undefined"!=typeof self?self:global);var k="undefined"!=typeof Symbol&&Symbol.toStringTag;O.get=function(e){var t=this[E][e];if(t&&null===t.e&&!t.E)return t.er?null:t.n},O.set=function(t,n){try{new URL(t)}catch(s){console.warn(Error(e("W3",'"'+t+'" is not a valid URL to set in the module registry')))}var r;k&&"Module"===n[k]?r=n:(r=Object.assign(Object.create(null),n),k&&Object.defineProperty(r,k,{value:"Module"}));var i=Promise.resolve(r),o=this[E][t]||(this[E][t]={id:t,i:[],h:!1,d:[],e:null,er:void 0,E:void 0});return!o.e&&!o.E&&(Object.assign(o,{n:r,I:void 0,L:void 0,C:i}),r)},O.has=function(e){return!!this[E][e]},O.delete=function(e){var t=this[E],n=t[e];if(!n||n.p&&null!==n.p.e||n.E)return!1;var r=n.i;return n.d&&n.d.forEach((function(e){var t=e.i.indexOf(n);-1!==t&&e.i.splice(t,1)})),delete t[e],function(){var n=t[e];if(!n||!r||null!==n.e||n.E)return!1;r.forEach((function(e){n.i.push(e),e(n.n)})),r=null}};var U="undefined"!=typeof Symbol&&Symbol.iterator;O.entries=function(){var e,t,n=this,r=Object.keys(n[E]),i=0,o={next:function(){for(;void 0!==(t=r[i++])&&void 0===(e=n.get(t)););return{done:void 0===t,value:void 0!==t&&[t,e]}}};return o[U]=function(){return this},o}}(); 5 | //# sourceMappingURL=system.min.js.map -------------------------------------------------------------------------------- /js-modules/README.md: -------------------------------------------------------------------------------- 1 | # rollup输出的6种格式 2 | 3 | ## 学习本文 📖 4 | 你将: 5 | 1. 弄明白rollup输出的6种格式,了解它们之间的关系和使用场景。 6 | 2. 获得一份最简单的 `rollup.js` 打包 `demo` 一份。 7 | 3. 这份 `demo` 还为每个打包结果准备了一个可执行 `demo of demo` 8 | 9 | ## 为什么要学这个? 10 | 伴随着 `vite.js` 越来越火,它也变成了工作生产和**面试问答**时被经常提及的问题。 11 | 12 | 众所周知,`vite.js` 构建的核心是 `rollup.js`。 13 | 14 | 那为什么在学习它们之前,有必要先学习 `js` 模块化规范? 15 | 16 | 因为我们需要理解它们最终的产物是什么,是如何运作的。 17 | 18 | “崇拜魔法”是编程学习者的大忌,“好奇心”才是我们成长与进步的阶梯。 19 | 20 | 让我们解开神秘的面纱,看看那些打包后的代码,都是些“什么玩意儿”! 21 | 22 | ## DEMO与示例构建 23 | > 请配合 `demo` 食用,你会收获更多! 24 | 25 | 我为本文构建了一个简单的 `demo` 实例,源码就放在 `github` 上。 26 | 27 | `demo` 地址: [https://github.com/zhangshichun/rollup-demos/tree/master/js-modules](https://github.com/zhangshichun/rollup-demos/tree/master/js-modules) 28 | 29 | `demo` 的代码结构如下: 30 | 31 | ```bash 32 | ├── answer.js 33 | ├── index.js 34 | ├── out 35 | ├── package.json 36 | ├── rollup.config.js 37 | └── yarn.lock 38 | ``` 39 | 其中 `index.js` 和 `answer.js` 属于业务代码,是需要被打包的对象。在 `index.js` 中依赖了 `answer.js`。 40 | 如下: 41 | ```js 42 | // answer.js 43 | export default 42 44 | 45 | // index.js 46 | import answer from "./answer"; 47 | import { repeat } from 'lodash' 48 | // 定义一个无用变量, 测试 tree-shaking 49 | const unusedVar = 'May the 4th' 50 | 51 | export const printAnswer = () => { 52 | // 打印 53 | console.log(`the answer is ${answer}`) 54 | // 测试 lodash 的能力,打印42个1 55 | console.log(repeat('1', answer)) 56 | } 57 | ``` 58 | `rollup.config.js` 是 `rollup` 的配置文件,在此文件中我们分别指定其输出 `amd` , `cjs` , `esm` , `iife` , `umd` , `system` 六种格式的文件。 59 | 60 | 输出的文件会被打包到 `out` 文件夹下。 61 | 62 | 当我们执行 `yarn build` 或者 `npm build` 之后,会在 `out` 下产生如下格式的代码: 63 | 64 | ```bash 65 | ├── out 66 | │   ├── amd 67 | │   │   └── bundle.js 68 | │   ├── cjs 69 | │   │   └── bundle.js 70 | │   ├── ems 71 | │   │   └── bundle.js 72 | │   ├── iife 73 | │   │   └── bundle.js 74 | │   ├── system 75 | │   │   └── bundle.js 76 | │   └── umd 77 | │   └── bundle.js 78 | ``` 79 | 为了弄清楚每种格式的 `bundle.js` 文件是如何运作的,我专门为它们订制添加了一些附属的小 `demo`。 80 | 81 | 接下来,就让我们一种格式一种格式地学习和分析吧。 82 | ![勇敢牛牛](https://cdn.jsdelivr.net/gh/zhangshichun/blog-images/imgs/2022-01-09-11.png) 83 | ## 一、IIFE 自执行函数 84 | > IIFE 的全称是 “immediately invoked function expression”。 85 | 86 | ### 1.1 打包结果分析 87 | 让我们先看看本 `demo` 的 `iife` 格式打出来的包长什么样。 88 | 89 | ![IIFE](https://cdn.jsdelivr.net/gh/zhangshichun/blog-images/imgs/2022-01-08-06.png) 90 | 91 | 对上述代码做一些简化: 92 | ```javascript 93 | var Test = (function (exports, lodash) { 94 | 'use strict'; // 自带严格模式,避免一些奇怪的兼容性问题 95 | 96 | /** 97 | * 下面折行无用代码被 tree-shaking 掉了 98 | * const unusedVar = 'May the 4th' 99 | * */ 100 | 101 | var answer = 42; // 业务中被单一引用的模块,被直接抹平了 102 | 103 | const printAnswer = () => { 104 | console.log(`the answer is ${answer}`); 105 | 106 | console.log(lodash.repeat('1', answer)); 107 | }; 108 | 109 | exports.printAnswer = printAnswer; // 把要export的属性挂在到exports上 110 | 111 | return exports; 112 | 113 | })({}, $); // exports是第一个入参,依赖的jquery是第二个入参 114 | 115 | ``` 116 | 117 | `IIFE` 是前端模块化早期的产物,它的核心思路是: 118 | 1. 构建一个匿名函数 119 | 2. 立刻执行这个匿名函数,对外部的依赖通过入参的形式传入 120 | 3. 返回该模块的输出 121 | 122 | ### 1.2 如何运行 123 | `IIFE` 的运行其实很容易,如果它没有其他依赖,只需要去引入文件,然后在 `window` 上取相应的变量即可。 124 | 如: 125 | 126 | ```html 127 | 128 | 132 | 133 | ``` 134 | 但是如果你像本 `demo` 中那样依赖了其他的模块,那你就必须保证以下两点才能正常运行: 135 | 1. 此包所依赖的包,已在此包之前完成加载。 136 | 2. 前置依赖的包,和 `IIFE` 只执行入参的变量命名是一致的。 137 | 138 | 以本 `demo` 的 `IIFE` 构建结果为例: 139 | 1. 它前置依赖了 `lodash`,因此需要在它加载之前完成 `lodash` 的加载。 140 | 2. 此 `IIFE` 的第二个入参是 `lodash`,作为前置条件,我们需要让 `window.lodash` 也指向 `lodash`。 141 | 因此,运行时,代码如下: 142 | ```html 143 | 144 | 145 | 146 | 147 | 148 | 149 | 152 | 153 | ``` 154 | ### 1.3 优缺点 155 | 156 | - 优点: 157 | 1. 通过闭包营造了一个“私有”命名空间,防止影响全局,并防止被从外部修改私有变量。 158 | 2. 简单易懂 159 | 3. 对代码体积的影响不大 160 | - 缺点: 161 | 1. 输出的变量可能影响全局变量;引入依赖包时依赖全局变量。 162 | 2. 需要使用者自行维护 `script` 标签的加载顺序。 163 | 164 | 优点就不细说了,缺点详细解释一下。 165 | 166 | **缺点一:输出的变量可能影响全局变量;引入依赖包时依赖全局变量**。 167 | 168 | 前半句:**输出的变量可能影响全局变量;** 其实很好理解,以上面 `demo` 的输出为例: `window.Test` 就已经被影响了。 169 | 这种明显的副作用在程序中其实是有隐患的。 170 | 171 | 后半句:**引入依赖包时依赖全局变量;** 我们为了让 `demo` 正常运行,因此加了一行代码让 `window.lodash` 也指向 `lodash`,但它确实是太脆弱了。 172 | 173 | ```html 174 | 175 | 176 | ``` 177 | 你瞧,`IIFE` 的执行对环境的依赖是苛刻的,除非它完全不依赖外部包。(Jquery: 正是在下!) 178 | 179 | 虽然 `IIFE` 的缺点很多,但并不妨碍它在 `Jquery` 时代极大地推动了 `web` 开发的进程,因为它确实解决了 `js` 本身存在的很多问题。 180 | 181 | 那么?后续是否还有 **更为优秀** 的前端模块化方案问世呢? 182 | 183 | 当然有,往下看吧。 184 | 185 | ## 二、CommonJS 186 | ### 2.1 分析打包结果 187 | 先看看 `CommonJs` 打包的结果: 188 | ![cjs](https://cdn.jsdelivr.net/gh/zhangshichun/blog-images/imgs/2022-01-08-5.png) 189 | 简化一下,就长这样了: 190 | ```js 191 | 'use strict'; 192 | 193 | var lodash = require('lodash'); 194 | 195 | var answer = 42; 196 | 197 | const printAnswer = () => { 198 | // 打印 199 | console.log(`the answer is ${answer}`); 200 | // 测试 lodash 的能力,打印42个1 201 | console.log(lodash.repeat('1', answer)); 202 | }; 203 | 204 | exports.printAnswer = printAnswer; 205 | 206 | ``` 207 | 以上格式,就是 `CommonJS` 规范的写法。 208 | 209 | ```js 210 | // CommonJS 通过一个全局 require 方法进行模块的引入 211 | var lodash = require('lodash'); 212 | // CommonJS 进行模块内方法输出的方式 213 | module.exports.printAnswer = printAnswer; 214 | // 上面写法也等价于: 215 | exports.printAnswer = printAnswer; 216 | // 因为 exports 变量等价于 module.exports 217 | ``` 218 | 219 | 为了解决 `node.js` 在模块化上的缺失, **2009年10月** `CommonJS` 规范首次被提出。 220 | 221 | 注意这个关键词: **node.js**。 222 | 223 | 是的,`CommonJS` 并不是在浏览器环境运行的规范,而是在 `node.js` 环境下运行的。 224 | ### 2.2 如何运行 225 | 因此,我写了一个 `run.js` 脚本。 226 | 如下: 227 | ```js 228 | // run.js 229 | const Test = require('./bundle-by-lodash') 230 | Test.printAnswer() 231 | ``` 232 | 然后,执行以下命令: 233 | ```bash 234 | # 执行脚本 235 | node ./out/cjs/run.js 236 | # 输出1: 237 | > the answer is 42 238 | # 输出2: 239 | > 111111111111111111111111111111111111111111 240 | ``` 241 | 可以看出,`node.js` 环境是天然支持 `CommonJS` 的。 242 | 243 | ### 2.3 优缺点 244 | - 优点 245 | 1. 完善的模块化方案,完美解决了 `IIFE` 的各种缺点。 246 | 247 | - 缺点 248 | 1. 不支持浏览器环境,因为这种同步的引入方式可能导致浏览器假死。 249 | 250 | 因此,前端界迫切地需要一种能在浏览器环境完美运行,完善的模块化方案。 251 | 252 | ## 三、AMD 和 requirejs ! 253 | > AMD,YES! 254 | 255 | 2011年, `amdjs-api` 在业内被正式提出。 256 | 257 | ### 3.1 打包结果分析 258 | amd 格式的打包结果如下: 259 | ![amd,yes!](https://cdn.jsdelivr.net/gh/zhangshichun/blog-images/imgs/2022-01-08-03.png) 260 | 可以看到,核心内容是一个全局方法 `define` 。 261 | 262 | `define` 方法有三个入参,分别是: 263 | - `"Test"`, 模块名称 264 | - `[`exports`, `lodash`]` 分别表示模块的输出和外部依赖 265 | - 一个以 `exports` 和 `lodash` 作为入参的方法,代表模块的实际内容。 266 | 267 | 相比于 `IIFE` 和 `CommonJs` 而言,`AMD` 的写法无疑是复杂且别扭的。 268 | 269 | 但它却实实在在是解决了 `IIFE` 和 `CommonJS` 所面临的问题,对“浏览器里完善的JS模块方法” 提供了一套完善的方案。 270 | 271 | 尤其是 `amd` 标准的实现方案:`requirejs`。 272 | 273 | `requirejs` 所实现的 `AMD` 不仅解决了 `CommonJS` 在浏览器端的不适,通过异步的方式进行模块加载实现了不会导致假死的能力;更是完全弥补了 `IIFE` 存在的各类缺陷。 274 | 275 | `requirejs` 在使用时,一般情况下是以下四步法: 276 | 1. 在浏览器内引入 `require.js` 277 | 2. 通过 `requirejs.config` 方法定义全局的依赖 278 | 3. 通过 `requirejs.define` 注册模块 279 | 4. 通过 `requirejs()` 完成模块引入。 280 | 281 | ### 3.2 如何运行 282 | 在 `out/amd` 打包目录下的 `index.html` 里,按如下方式编排代码: 283 | ```html 284 | 285 | 286 | 287 | 288 | 295 | 296 | 297 | 298 | 299 | 308 | 309 | ``` 310 | 打开浏览器,我们可以正常地看到]控制台里被打印出来的 `42` 和 `42个1` 了。 311 | 312 | ### 3.3 优缺点 313 | - 优点 314 | 1. 解决了 `CommonJS` 的缺点 315 | 2. 解决了 `IIFE` 的缺点 316 | 3. 一套完备的浏览器里 `js` 文件模块化方案 317 | - 缺点 318 | 1. 代码组织形式别扭,可读性差 319 | 320 | 但好在我们拥有了各类打包工具,浏览器内的代码可读性再差也并不影响我们写出可读性ok的代码。 321 | 322 | 现在,我们拥有了**面向 `node.js` 的 `CommonJs`** 和 **面向浏览器的 `AMD`** 两套标准。 323 | 324 | 如果我希望我写出的代码能同时被**浏览器**和**nodejs**识别,我应该怎么做呢? 325 | 326 | ## 四、UMD 伟大的整合 327 | > 它没有做什么突破性的创造,但它是集大成者。 328 | 329 | ### 4.1 打包分析 330 | `umd` 格式构建出来的代码的可读性进一步降低了。 331 | 332 | 我相信任何正常人看到下面这段代码都会感到一阵头大: 333 | 334 | ![umd bundle](https://cdn.jsdelivr.net/gh/zhangshichun/blog-images/imgs/2022-01-07-04.png) 335 | 336 | 是的,整整一大段代码,只是在处理兼容性问题,判断当前应该使用 `amd` 亦或是 `CommonJS`。 337 | 338 | 因此 `umd` 的代码和实现不在此进行过多分析,它所做的无非便是让同一段代码兼容了 `amd` 和 `CommonJS`。 339 | 340 | ### 4.2 如何运行? 341 | - 在浏览器端,它的运行方式和 `amd` 完全一致,可以完全参考 `3.2` 节的 `demo`。 342 | - 在node.js端,它则和 `CommonJS` 的运行方式完全一致,在此就不赘述了。 343 | 344 | ### 4.3 优缺点 345 | - 优点 346 | 1. 抹平了一个包在 `AMD` 和 `CommonJS` 里的差异 347 | - 缺点 348 | 1. 会为了兼容产生大量不好理解的代码。(理解难度与包体积) 349 | 350 | 351 | 虽然在社区的不断努力下,`CommonJS` 、 `AMD` 、 `UMD` 都给业界交出了自己的答卷。 352 | 353 | 但很显然,它们都是不得已的选择。 354 | 355 | 浏览器应该有自己的加载标准。 356 | 357 | `ES6` 草案最终版里,虽然描述了模块应该如何被加载,但它没有 “加载程序的规范”。 358 | 359 | ## 五、SystemJs 360 | 因此 `WHATWG(Web Hypertext Application Technology Working Group)` 即网页超文本应用技术工作小组,提出了一套更有远见的规范:[whatwg/loader](https://github.com/whatwg/loader)。 361 | 362 | 也就是 `JavaScript Loader Standard` (JS 加载标准)。 363 | 364 | > 本规范描述了从 JavaScript 宿主环境中加载 JavaScript 模块的行为。它还提供了用于拦截模块加载过程和自定义加载行为的 api。 365 | 366 | 基于此规范,`SystemJS` 诞生了。 367 | 368 | `SystemJS` 是目前 `whatwg/loader` 规范的最佳实践者。 369 | 370 | ![systemjs bundle](https://cdn.jsdelivr.net/gh/zhangshichun/blog-images/imgs/2022-01-08-01.png) 371 | 372 | 可以看出来,`system` 的打包结果其实和 `amd` 类似,提供了全局的对象 `System`,并提供了注册的方式和统一的写法。 373 | 374 | 就单纯的从打包结果上,其实看不出它相比对 `AMD + require.js` 有什么优势,**难道只是写法上存在差异**? 375 | 376 | 并不止于此! 377 | 378 | 相比于 `require.js`,`SystemJS` 的 `System.import('module/name')` 方式允许你更为“懒”地加载模块,这意味着你无需每次都加载一大堆的 `bundle`,用户只需要为他能看见的页面开销带宽。 379 | 380 | 另外,正因为 `SystemJS` 是面向 `whatwg/loader` 规范实践的,因此它是面向未来的模块依赖方式。 381 | 382 | > 抱歉,这个的 demo 我也没玩明白,就不误导大家了。希望有明白的大佬可以帮忙完善下demo。 383 | 384 | ## 六、ESM 385 | > ECMAScript modules, 也叫 ESM, Javascript 模块化官方标准格式。 386 | 387 | ### 6.1 打包分析 388 | 389 | 在 `ESM` 被提出来之前,JavaScript 一直没有真正意义上的模块(module)体系。 390 | 391 | 它的规范是通过 `export` 命令显式指定输出的代码,再通过 `import` 命令输入。 392 | ```javascript 393 | // 导入模块 394 | import { foo } from 'bar'; 395 | // 导出命令 396 | export { zap }; 397 | ``` 398 | 这也是我们日常开发中最为熟悉的写法。 399 | 400 | 因此,`esm` 格式打出来的包,可读性确实非常棒: 401 | ![esm](https://cdn.jsdelivr.net/gh/zhangshichun/blog-images/imgs/2022-01-08-09.png) 402 | 403 | 和阅读我们平时所写的业务代码完全没有区别。(`rollup` 依然没忘记做 `tree-shaking`) 404 | 405 | ### 6.2 如何运行 406 | > 祝贺你,是这个时代的前端开发。 407 | 408 | 部分现代浏览器已经开始实装 ` 268 | 269 | 270 | ``` 271 | 272 | ## 七、inject 插件 273 | > 官方简介:一个 Rollup 插件,用于扫描模块的全局变量,并在必要时注入`import`语句。 274 | 275 | 这个简介其实还算中规中矩。 276 | 277 | 我稍微翻译下: 278 | 279 | > 你可以将一些模块定义为“全局变量”,在项目中使用时无需再写 `import` 语句。实际在构建时,此组件会发现它们并自动在文件中补全 `import` 语句。 280 | 281 | 比如,可以将 `lodash` 定义为全局变量 `_`,这样就可以随时随地地使用 `_.xxx`,并且在构建时,此插件会自动帮你补全: 282 | `import _ from 'lodash'`。 283 | 284 | `demo`详解: 285 | `index.js`: 286 | ```js 287 | export const printAnswer = () => { 288 | console.log(_.includes([1,2,3], 1)) 289 | } 290 | ``` 291 | 以上直接使用了一个未曾定义的全局变量 `_`,正常构建肯定会报错。 292 | 293 | 对照组: 294 | 1. 不使用`@rollup/plugin-inject` 插件,构建(执行 `yarn build-inject-no-plugin`)的构建产物:**代码毫无变化**。 295 | 296 | 2. 使用`@rollup/plugin-inject` 插件,构建(执行 `yarn build-inject`)的构建产物: 297 | ```js 298 | import _ from 'lodash'; 299 | 300 | const printAnswer = () => { 301 | console.log(_.includes([1,2,3], 1)); 302 | }; 303 | 304 | export { printAnswer }; 305 | ``` 306 | 构建产物里,按需引入了`lodash`,非常智能。 307 | 308 | ## 八、multi-entry 插件 309 | 310 | > 官方简介:一个 `Rollup` 插件,允许对一个 `bundle` 使用多个入口点。 311 | 312 | 官方简介其实表示的还挺明白的,多个入口的文件,可以打包到一个 `bundle` 之中。 313 | 314 | demo详解: 315 | `a.js` 316 | ```js 317 | export const printHello = () => { 318 | console.log('hello') 319 | } 320 | ``` 321 | `b.js` 322 | ```js 323 | export const printHello = () => { 324 | console.log('hello') 325 | } 326 | ``` 327 | 把 `rollup` 的配置文件也做一定改动: 328 | ```js 329 | export default { 330 | input: [path.resolve(__dirname, './a.js'), path.resolve(__dirname, './b.js')], 331 | output: { 332 | dir: path.resolve(__dirname, 'out'), 333 | format: 'esm' 334 | }, 335 | }; 336 | ``` 337 | 338 | 对照组: 339 | 1. 不使用 `@rollup/plugin-multi-entry` 插件,在构建(执行命令 `yarn build-multi-entry-no-plugin`)之后,其产出为: 340 | ```js 341 | out/a.js 342 | // 和 343 | out/b.js 344 | ``` 345 | 是的,并没有被合并到一个 `bundle` 中。 346 | 347 | 2. 使用 `@rollup/plugin-multi-entry` 插件,在构建(执行命令 `yarn build-multi-entry`)之后,其产出为: 348 | `out/multi-entry.js` 349 | ```js 350 | const printHello = () => { 351 | console.log('hello'); 352 | }; 353 | 354 | const printWorld = () => { 355 | console.log('world'); 356 | }; 357 | 358 | export { printHello, printWorld }; 359 | ``` 360 | 构建结果完成了合并,两个入口的内容出现在了一个 `bundle` 之中。 361 | 362 | ## 九、replace 插件 363 | 364 | > 官方简介:一个 Rollup 插件,在打包时替换文件中的目标字符串。 365 | 366 | ![](https://files.mdnice.com/user/23675/17eae556-59fc-4b6a-87c5-3841f287744b.png) 367 | 368 | 可以,官方简介很准确。 369 | 370 | `demo`详解: 371 | 372 | 假设一个场景:你希望每次访问页面时,都能快速知道本包是何时构建的,应该怎么做? 373 | 374 | 很简单,使用本插件: `@rollup/plugin-replace`。 375 | 376 | 只需要在代码中如下定义: 377 | 378 | ```js 379 | window.buildTime = "__build_time__"; 380 | ``` 381 | 然后在 `rollup` 配置中通过 `@rollup/plugin-replace` 插件,将当前构建的时间戳格式化后赋值给 `__build_time__`,即可实现功能。 382 | 383 | 对照组: 384 | 1. 不使用 `@rollup/plugin-replace` 插件,构建(执行命令 `yarn build-replace-no-plugin`)产物: 385 | 386 | ```js 387 | window.buildTime = "__build_time__"; 388 | ``` 389 | 2. 使用 `@rollup/plugin-replace` 插件,构建(执行命令 `yarn build-replace`)产物: 390 | ```js 391 | window.buildTime = "2022-02-23 22:11:04"; 392 | ``` 393 | 哈哈,同理,打组件包时,想知道构建 `version` 也可以用这个思路。 394 | 395 | ## 十、run 插件 396 | 397 | > 官方简介:一个 `Rollup` 插件,一旦你的 `bundle` 被构建,它就会在 `nodejs` 中运行。 398 | 399 | 不错的官方简介! 400 | 401 | 这显然是为一些 `node` 脚本或者 `node` 服务订制的能力,构建后会立刻运行或启动一个服务。 402 | 403 | demo详解:(这就不配对照组了) 404 | `index.js`: 405 | ```js 406 | const printAnswer = () => { 407 | console.log('hello world') 408 | } 409 | 410 | printAnswer() 411 | ``` 412 | 使用`@rollup/plugin-run` 插件构建(执行命令 `yarn build-run`)之后,控制台输出: 413 | ```bash 414 | created run/out/bundle.js in 11ms 415 | hello world 416 | Done in 0.15s. 417 | ``` 418 | 直接执行了构建内容,输出了 `hello world`。 419 | 420 | ## 十一、strip 插件 421 | 422 | > 官方简介:一个 Rollup 插件,用于从代码中删除 `debugger` 语句和诸如 `assert.equal` 和 `console.log` 类似的函数。 423 | 424 | emmm...很清晰的简介,点赞。 425 | 426 | `demo` 详解: 427 | `index.js` 428 | ```js 429 | export const printAnswer = () => { 430 | console.log('hello, boy') 431 | return 42; 432 | } 433 | ``` 434 | 对照组: 435 | 1. 不使用 `@rollup/plugin-strip` 插件,构建(`yarn build-trip-no-plugin`)产物: 436 | ```js 437 | const printAnswer = () => { 438 | console.log('hello, boy'); 439 | return 42; 440 | }; 441 | 442 | export { printAnswer }; 443 | ``` 444 | 445 | 2. 使用 `@rollup/plugin-strip` 插件,构建(`yarn build-trip`)产物: 446 | ``` 447 | const printAnswer = () => { 448 | return 42; 449 | }; 450 | export { printAnswer }; 451 | ``` 452 | 在生产构建时,这个插件还是很重要的,避免将一些 `debugger` 语句带入生产环境,毕竟 `console.log` 还是有性能开销的。 453 | 454 | ## 十二、url 插件 455 | > 官方简介:一个 `Rollup` 插件,将文件导入为 `data-URIs` 或 `esm` 格式。 456 | 457 | ![](https://cdn.jsdelivr.net/gh/zhangshichun/blog-images/imgs/2022-02-25-01.png) 458 | 459 | 这样说或者有些让人摸不着头脑,通过 `demo` 或许能更容易理解。 460 | 461 | `demo` 详解: 462 | `index.js` 分别引入了两个 `.png` 格式文件,分别为: 463 | ```js 464 | // test.png 7KB 大小 465 | import test01 from './test.png' 466 | // test02.png 16KB 大小 467 | import test02 from './test02.png' 468 | ``` 469 | 当没有 `@rollup/plugin-url` 支持时,构建(`yarn build-url-no-plugin`)行为一定会报错,因为 `js` 解析引擎无法解析 `.png` 格式的文件。 470 | 471 | 但配上 `@rollup/plugin-url` 插件后,结果会怎样呢? 472 | 473 | ``` 474 | var test01 = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAOcAAAD2CAYAAAAtfpAeAAAAAXNS...(略)"; 475 | 476 | var test02 = "7822ffd3c90c0d9c.png"; 477 | ``` 478 | 对于两张图片的处理居然并不相同! 479 | 为什么呢? 480 | 官方文档解释: 481 | > 内联文件的文件大小限制。如果一个文件超过这个限制(默认14KB),它将被复制到目标文件夹,并提供散列文件名。 482 | 483 | 因此, `test02.png` 被复制到了目标文件夹,并提供了一个新的基于散列的名称,而且导入的 `test02` 并不是文件,而是该文件的路径。 484 | 485 | 那么 `test` 呢? 486 | 487 | `test` 是作为 `data URIs` 被导入的,关于这种格式,想详细了解的可以访问此文档查看: 488 | [http://nodejs.cn/api/esm.html#data-imports](http://nodejs.cn/api/esm.html#data-imports) 489 | 490 | 简单来说,通过这种形式将 `文件` 作为内联形式引入,可以减少网络请求的次数,提升页面加载速度。 491 | 492 | (这也是为什么此插件针对小文件和大文件要采取不一样的策略的原因。) 493 | 494 | ## 十三、post-css 插件 495 | (非rollup官方仓库直接推荐的插件)地址:[https://github.com/egoist/rollup-plugin-postcss](https://github.com/egoist/rollup-plugin-postcss) 496 | > 官方简介:`Rollup` 和 `PostCSS` 之间的无缝集成。 497 | 498 | 为什么要推荐这个插件?因为它太强了! 499 | 500 | 它不仅仅是一个插件这么简单,因为使用它,你可以获得 `PostCSS` 整个社区的生态力量。 501 | 502 | 众所周知,`PostCSS` 本身就拥有自己的`插件系统`,在集成本插件之后,你将可以导入各种 `postcss 插件`,完成关于 `css` 的各种复杂操作。 503 | ![](https://cdn.jsdelivr.net/gh/zhangshichun/blog-images/imgs/2022-02-26-01.png) 504 | **ALL IN ONE! AMAZING!** 505 | 506 | `demo` 详解: 507 | `index.js` 508 | ```js 509 | import './style.scss' 510 | export const printAnswer = () => { 511 | console.log('answer is 42') 512 | } 513 | ``` 514 | `style.scss` 515 | ```scss 516 | .bg { 517 | color: red; 518 | 519 | .title { 520 | color: black; 521 | } 522 | } 523 | ``` 524 | 因为 `rollup.js` 本身是不支持 `css` 格式的,更是不支持 `scss` 格式的。 525 | 526 | 因此我们的思路是: 527 | 528 | 构建时引入 `rollup-plugin-css` 插件,并通过配置让它支持 `scss` 的编译和链接支持。 529 | 530 | ```js 531 | export default { 532 | ... 533 | plugins: [ 534 | postcss({ 535 | extract: true, // css通过链接引入 536 | use: ["sass"], // 编译 sass 537 | }) 538 | ], 539 | ... 540 | }; 541 | ``` 542 | 543 | 执行命令: `yarn build-post-css` 544 | 545 | 输出: 546 | `bundle.css` 547 | ```css 548 | .bg { 549 | color: red; 550 | } 551 | .bg .title { 552 | color: black; 553 | } 554 | ``` 555 | 完美。 556 | 557 | ## 十四、那些未提供 `demo` 的插件 558 | 559 | 因为本文篇幅有限,很多“官方推荐”的插件也并未能全部提供插件,其中以“格式解析”类为主,比如: 560 | 1. `@rollup/plugin-dsv` 561 | 2. `@rollup/plugin-graphql` 562 | 3. `@rollup/plugin-image` 563 | 4. `@rollup/plugin-json` 564 | 5. `@rollup/plugin-wasm` 565 | 6. `@rollup/plugin-yaml` 566 | 567 | 以上这些都专注于解决一件事:“之前 `rollup` 不支持 `xx` 格式的文件,现在我想办法让它支持”。 568 | 569 | 当我们需要使用时,看看文档,通常就能很快上手,没啥理解难度。 570 | 571 | > 除此之外,还有一些比较冷门的插件,也没列出来细说。 572 | 573 | ## 十五、地址汇总: 574 | 575 | 1. 我的另一篇 `rollup` 相关文章:《说不清rollup能输出哪6种格式😥差点被鄙视》[https://juejin.cn/post/7051236803344334862](https://juejin.cn/post/7051236803344334862) 576 | 577 | 2. `@rollup/plugins` 官方 `github`:[https://github.com/rollup/plugins](https://github.com/rollup/plugins) 578 | 579 | 3. 本文 `demo` 地址:[https://github.com/zhangshichun/rollup-demos/tree/master/base-plugins](https://github.com/zhangshichun/rollup-demos/tree/master/base-plugins) 580 | 581 | 4. `rollup-plugin-postcss`地址:[https://github.com/egoist/rollup-plugin-postcss](https://github.com/egoist/rollup-plugin-postcss) 582 | 583 | ## 十六、结束语 584 | 585 | 我是`春哥`。 586 | 大龄前端打工仔,依然在努力学习。 587 | 我的目标是给大家分享最实用、最有用的知识点,希望大家都可以早早下班,并可以飞速完成工作,淡定摸鱼🐟。 588 | 589 | 你可以在**公众号**里找到我:`前端要摸鱼`。 590 | -------------------------------------------------------------------------------- /js-modules/out/amd/require.js: -------------------------------------------------------------------------------- 1 | /** vim: et:ts=4:sw=4:sts=4 2 | * @license RequireJS 2.3.6 Copyright jQuery Foundation and other contributors. 3 | * Released under MIT license, https://github.com/requirejs/requirejs/blob/master/LICENSE 4 | */ 5 | var requirejs,require,define;!function(global,setTimeout){var req,s,head,baseElement,dataMain,src,interactiveScript,currentlyAddingScript,mainScript,subPath,version="2.3.6",commentRegExp=/\/\*[\s\S]*?\*\/|([^:"'=]|^)\/\/.*$/gm,cjsRequireRegExp=/[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,jsSuffixRegExp=/\.js$/,currDirRegExp=/^\.\//,op=Object.prototype,ostring=op.toString,hasOwn=op.hasOwnProperty,isBrowser=!("undefined"==typeof window||"undefined"==typeof navigator||!window.document),isWebWorker=!isBrowser&&"undefined"!=typeof importScripts,readyRegExp=isBrowser&&"PLAYSTATION 3"===navigator.platform?/^complete$/:/^(complete|loaded)$/,defContextName="_",isOpera="undefined"!=typeof opera&&"[object Opera]"===opera.toString(),contexts={},cfg={},globalDefQueue=[],useInteractive=!1;function commentReplace(e,t){return t||""}function isFunction(e){return"[object Function]"===ostring.call(e)}function isArray(e){return"[object Array]"===ostring.call(e)}function each(e,t){var i;if(e)for(i=0;i