предисловие
В предыдущем туториале вам познакомили с вводными навыками rollup.js.Кто не читал может нажатьздесь, в этот раз мы продолжим обсуждение продвинутых навыков rollup.js, а те, кто хочет прочитать непосредственно заключение, могут прочитать последнюю главу.
Плагин rollup.js
Плагин rollup.js имеет подключаемый дизайн, который помогает нам улучшить основные функции rollup.js.Ниже я сосредоточусь на четырех наиболее часто используемых плагинах rollup.js.
разрешить плагин
Зачем нужен плагин разрешения?
В предыдущем туториале упаковываемые нами объекты — это локальный js-код и библиотеки, но в реальной разработке маловероятно, что все библиотеки расположены локально, мы будем скачивать удаленные библиотеки через npm. Здесь я специально подготовил несколько тестовых библиотек, чтобы все могли их использовать при изучении rollup.js.Сначала скачайте тестовую библиотеку:
npm i -S sam-test-data
Библиотека sam-test-data по умолчанию предоставляет модуль UMD, который предоставляет две переменные a и b и случайную функцию. случайной функции является целым числом. Например, если передать 100, она вернет случайное целое число от 0 до 99 и создаст папку для кода тестового плагина локально:
mkdir src/plugin
Создайте тестовый код:
touch src/plugin/main.js
Напишите следующий код:
import * as test from 'sam-test-data'
console.log(test)
export default test.random
Не упаковывайте сначала с помощью rollup.js и попробуйте запустить код напрямую через babel-node:
babel-node
> require('./src/plugin/main.js')
{ a: 1, b: 17, random: [Function: random] }
{ default: [Function: random] }
> require('./src/plugin/main.js').default(100)
41
Вы можете видеть, что код может работать нормально, попробуем упаковать код через rollup.js и добавить новый файл конфигурации:
touch rollup.plugin.config.js
Напишите следующее:
import { comment } from './comment-helper-es'
export default {
input: './src/plugin/main.js',
output: [{
file: './dist/index-plugin-cjs.js',
format: 'cjs',
banner: comment('welcome to imooc.com', 'this is a rollup test project'),
footer: comment('powered by sam', 'copyright 2018')
}, {
file: './dist/index-plugin-es.js',
format: 'es',
banner: comment('welcome to imooc.com', 'this is a rollup test project'),
footer: comment('powered by sam', 'copyright 2018')
}]
}
Здесь я предоставляю модуль comment-helper-es, который предоставляет метод комментирования, автоматически считывает наши параметры и помогает генерировать комментарии. В то же время над и под комментарием будет добавлен разделитель одинаковой длины. Заинтересованные партнеры могут использовать это напрямую:
export function comment() {
if (arguments.length === 0) {
return // 如果参数为0直接返回
}
let maxlength = 0
for (let i = 0; i < arguments.length; i++) {
const length = arguments[i].toString().length
maxlength = length > maxlength ? length : maxlength // 获取最长的参数
}
maxlength = maxlength === 0 ? maxlength : maxlength + 1 // 在最长参数长度上再加1,为了美观
let seperator = ''
for (let i = 0; i < maxlength; i++) {
seperator += '=' // 根据参数长度生成分隔符
}
const c = []
c.push('/**\n') // 添加注释头
c.push(' * ' + seperator + '\n') // 添加注释分隔符
for (let i = 0; i < arguments.length; i++) {
c.push(' * ' + arguments[i] + '\n') // 加入参数内容
}
c.push(' * ' + seperator + '\n') // 添加注释分隔符
c.push(' **/') // 添加注释尾
return c.join('') // 合并参数为字符串
}
Упаковано через rollup.js:
$ rollup -c rollup.plugin.config.js
./src/plugin/main.js → ./dist/index-plugin-cjs.js, ./dist/index-plugin-es.js...
(!) Unresolved dependencies
https://rollupjs.org/guide/en#warning-treating-module-as-external-dependency
sam-test-data (imported by src/plugin/main.js)
created ./dist/index-plugin-cjs.js, ./dist/index-plugin-es.js in 13ms
Вы можете видеть, что генерация кода прошла успешно, но на sam-test-data ссылаются как на внешний модуль Давайте просмотрим исходный код dist/index-plugin-es.js:
/**
* ==============================
* welcome to imooc.com
* this is a rollup test project
* ==============================
**/
import * as test from 'sam-test-data';
import { random } from 'sam-test-data';
console.log(test);
var main = random;
export default main;
/**
* ===============
* powered by sam
* copyright 2018
* ===============
**/
Это почти то же самое, что код, который мы написали изначально, за исключением того, что случайная функция получается из sam-test-data отдельно через деструктурирующее присваивание es6, а затем присваивается переменной main и экспонируется. Только представьте, если мы пишем библиотеку классов Javascript, когда пользователи обращаются к нашей библиотеке, им нужно вручную загрузить все зависимости этой библиотеки, какой это плохой опыт. Чтобы решить эту проблему, объедините исходный код, который мы написали, с зависимыми сторонними библиотеками, и rollup.js предоставит нам подключаемый модуль разрешения.
Как использовать плагин разрешения
Сначала установите плагин разрешения:
npm i -D rollup-plugin-node-resolve
Измените файл конфигурации rollup.plugin.config.js:
import resolve from 'rollup-plugin-node-resolve'
export default {
input: './src/plugin/main.js',
output: [{
file: './dist/index-plugin-cjs.js',
format: 'cjs'
}, {
file: './dist/index-plugin-es.js',
format: 'es'
}],
plugins: [
resolve()
]
}
Переупаковка:
$ rollup -c rollup.plugin.config.js
./src/plugin/main.js → ./dist/index-plugin-cjs.js, ./dist/index-plugin-es.js...
created ./dist/index-plugin-cjs.js, ./dist/index-plugin-es.js in 28ms
Вы можете видеть, что предупреждение устранено, и мы повторно проверяем исходный код dist/index-plugin-es.js:
const a = Math.floor(Math.random() * 10);
const b = Math.floor(Math.random() * 100);
function random(base) {
if (base && base % 1 === 0) {
return Math.floor(Math.random() * base)
} else {
return 0
}
}
var test = /*#__PURE__*/Object.freeze({
a: a,
b: b,
random: random
});
console.log(test);
var main = random;
export default main;
Очевидно, исходный код библиотеки sam-test-data был интегрирован с нашим исходным кодом.
tree-shaking
Ниже мы модифицируем исходный код src/plugin/main.js:
import * as test from 'sam-test-data'
export default test.random
удалено из исходного кодаconsole.log(test)
, переупаковано:
rollup -c rollup.plugin.config.js
Просмотрите исходный код dist/index-plugin-es.js еще раз:
function random(base) {
if (base && base % 1 === 0) {
return Math.floor(Math.random() * base)
} else {
return 0
}
}
var main = random;
export default main;
Мы обнаружили, что определения переменных a и b пропали, потому что эти две переменные не используются в исходном коде. Вот чем славятся модули EStree-shakingМеханизм, он динамически удаляет неиспользуемый код, делая код более оптимизированным, так что наша библиотека классов может получить более высокую скорость загрузки (меньшая емкость, более высокая естественная скорость загрузки).
внешнее свойство
В некоторых сценариях, несмотря на то, что мы используем подключаемый модуль разрешения, мы по-прежнему сохраняем некоторые библиотеки во внешнем ссылочном состоянии.В этом случае нам нужно использовать внешний атрибут, чтобы сообщить rollup.js, какие внешние библиотеки классов, и изменить файл конфигурации rollup.js:
import resolve from 'rollup-plugin-node-resolve'
export default {
input: './src/plugin/main.js',
output: [{
file: './dist/index-plugin-cjs.js',
format: 'cjs'
}, {
file: './dist/index-plugin-es.js',
format: 'es'
}],
plugins: [
resolve()
],
external: ['sam-test-data']
}
Переупаковка:
rollup -c rollup.plugin.config.js
Посмотреть исходный код dist/index-plugin-es.js:
import { random } from 'sam-test-data';
var main = random;
export default main;
Видно, что несмотря на использование плагина разрешения, библиотека sam-test-data по-прежнему рассматривается как внешняя библиотека.
плагин commonjs
Зачем вам плагин commonjs?
rollup.js по умолчанию не поддерживает модуль CommonJS. Здесь я написал модуль CommonJS для тестирования. Содержание модуля точно такое же, как и у sam-test-data. Разница в том, что первый использует спецификацию CommonJS. Сначала установите этот модуль:
npm i -S sam-test-data-cjs
Создайте новый файл кода:
touch src/plugin/main-cjs.js
Напишите следующий код:
import test from 'sam-test-data-cjs'
console.log(test)
export default test.random
Этот код очень прост.Далее измените файл конфигурации rollup.js:
import resolve from 'rollup-plugin-node-resolve'
export default {
input: './src/plugin/main-cjs.js',
output: [{
file: './dist/index-plugin-cjs.js',
format: 'cjs'
}, {
file: './dist/index-plugin-es.js',
format: 'es'
}],
plugins: [
resolve()
]
}
Выполнить упаковку:
rollup -c rollup.plugin.config.js
./src/plugin/main-cjs.js → ./dist/index-plugin-cjs.js, ./dist/index-plugin-es.js...
[!] Error: 'default' is not exported by node_modules/_sam-test-data-cjs@0.0.1@sam-test-data-cjs/index.js
https://rollupjs.org/guide/en#error-name-is-not-exported-by-module-
src/plugin/main-cjs.js (1:7)
1: import test from 'sam-test-data-cjs'
^
Видно, что по умолчанию rollup.js не может распознать модуль CommonJS.На данный момент нам нужно использовать плагин commonjs для решения этой проблемы.
Как использовать плагин commonjs
Сначала установите плагин commonjs:
npm i -D rollup-plugin-commonjs
Измените файл конфигурации rollup.js:
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
export default {
input: './src/plugin/main-cjs.js',
output: [{
file: './dist/index-plugin-cjs.js',
format: 'cjs'
}, {
file: './dist/index-plugin-es.js',
format: 'es'
}],
plugins: [
resolve(),
commonjs()
]
}
Переоформить упаковку:
rollup -c rollup.plugin.config.js
После успешной упаковки проверяем исходный код dist/index-plugin-es.js:
const a = Math.floor(Math.random() * 10);
const b = Math.floor(Math.random() * 100);
function random(base) {
if (base && base % 1 === 0) {
return Math.floor(Math.random() * base)
} else {
return 0
}
}
var _samTestDataCjs_0_0_1_samTestDataCjs = {
a, b, random
};
console.log(_samTestDataCjs_0_0_1_samTestDataCjs);
var mainCjs = _samTestDataCjs_0_0_1_samTestDataCjs.random;
export default mainCjs;
См. Модуль Commonjs встроен в код, на Babel-Node пытается выполнить пакетированный код:
babel-node
> require('./dist/index-plugin-es')
{ a: 7, b: 45, random: [Function: random] }
{ default: [Function: random] }
> require('./dist/index-plugin-es').default(1000)
838
Код выполнен успешно, что указывает на то, что наш код успешно упакован.
CommonJS и древовидная тряска
Давайте изменим исходный код src/plugin/main-cjs.js, чтобы проверить, поддерживает ли модуль CommonJS функцию встряхивания дерева:
import test from 'sam-test-data-cjs'
export default test.random
Как и в случае с tree-shaking в разрешении, убираемconsole.log(test)
и повторно запустите упаковку, а затем просмотрите исходный код упаковки:
const a = Math.floor(Math.random() * 10);
const b = Math.floor(Math.random() * 100);
function random(base) {
if (base && base % 1 === 0) {
return Math.floor(Math.random() * base)
} else {
return 0
}
}
var _samTestDataCjs_0_0_1_samTestDataCjs = {
a, b, random
};
var mainCjs = _samTestDataCjs_0_0_1_samTestDataCjs.random;
export default mainCjs;
Видно, что переменные a и b по-прежнему определены в исходном коде, что указывает на то, что модуль CommonJS не может поддерживать функцию встряхивания дерева, поэтому рекомендуется максимально использовать модуль ES при упаковке с помощью свертки. js, чтобы получить более оптимизированный код.
UMD и встряхивание деревьев
Модуль UMD похож на CommonJS и не поддерживает функцию встряхивания дерева.Здесь я предоставляю тестовый модуль UMD sam-test-data-umd, и заинтересованные партнеры могут проверить его самостоятельно. Некоторые друзья могут спросить, sam-test-data также является модулем UMD, почему он поддерживает встряхивание деревьев? Давайте откроем package.json файла sam-test-data, чтобы узнать:
{
"name": "sam-test-data",
"version": "0.0.4",
"description": "provide test data",
"main": "dist/sam-test-data.js",
"module": "dist/sam-test-data-es.js"
}
Вы можете видеть, что основное свойство указывает на dist/sam-test-data.js, который является модулем UMD, но свойство модуля указывает на dist/sam-test-data-es.js, который является модулем ES, свертки .js по умолчанию Модуль, на который указывает атрибут модуля, будет найден и загружен первым. Поэтому модуль ES sam-test-data загружается предпочтительно для поддержки функции дрожания дерева. Давайте взглянем на официальное описание rollup.js:
Укажите текущую скомпилированную версию в основном свойстве файла package.json. Если в вашем package.json также есть поле модуля, инструменты с поддержкой ES6, такие как Rollup и webpack 2, будут напрямую импортировать версию модуля ES6.
Плагин Бабель
Зачем вам нужен плагин babel?
Создайте новый файл main-es.js в каталоге src/plugin:
touch src/plugin/main-es.js
Напишите следующий код:
import { a, b, random } from 'sam-test-data-es'
console.log(a, b, random)
export default (base) => {
return random(base)
}
Код принимает новые функции ES6: функция стрелки, изменение файла конфигурации:
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
export default {
input: './src/plugin/main-es.js',
output: [{
file: './dist/index-plugin-cjs.js',
format: 'cjs'
}, {
file: './dist/index-plugin-es.js',
format: 'es'
}],
plugins: [
resolve(),
commonjs()
]
}
Переоформить упаковку:
rollup -c rollup.plugin.config.js
Посмотреть исходный код dist/index-plugin-es.js:
var mainEs = (base) => {
return random(base)
};
export default mainEs;
Вы видите, что стрелочные функции сохранены, и такой код не будет работать в средах, не поддерживающих ES6. Мы ожидаем, что сможем использовать babel для завершения преобразования кода в процессе упаковки rollup.js, поэтому нам нужен подключаемый модуль babel.
Как использовать плагин Babel
Сначала установите плагин babel:
npm i -D rollup-plugin-babel
Измените файл конфигурации и добавьте ссылку на подключаемый модуль babel:
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
import babel from 'rollup-plugin-babel'
export default {
input: './src/plugin/main-es.js',
output: [{
file: './dist/index-plugin-cjs.js',
format: 'cjs'
}, {
file: './dist/index-plugin-es.js',
format: 'es'
}],
plugins: [
resolve(),
commonjs(),
babel()
]
}
Переупаковка:
rollup -c rollup.plugin.config.js
Просмотрите исходный код dist/index-plugin-es.js еще раз:
var mainEs = (function (base) {
return random(base);
});
export default mainEs;
Вы можете видеть, что стрелочная функция преобразована в функцию, и плагин babel работает правильно.
json-плагин
Зачем нужен плагин json
Создайте новый файл main-json.js в разделе src/plugin:
touch src/plugin/main-json.js
Импортируйте package.json как модуль и напечатайте имя и основные свойства в package.json:
import json from '../../package.json'
console.log(json.name, json.main)
Попробуйте выполнить main-json.js с помощью babel-node:
$ babel-node src/plugin/main-json.js
rollup-test index.js
Вы можете видеть, что печатаются и имя, и основные поля, и babel-node может правильно идентифицировать модуль json. Измените файл конфигурации rollup.js ниже:
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
import babel from 'rollup-plugin-babel'
export default {
input: './src/plugin/main-json.js',
output: [{
file: './dist/index-plugin-cjs.js',
format: 'cjs'
}, {
file: './dist/index-plugin-es.js',
format: 'es'
}],
plugins: [
resolve(),
commonjs(),
babel()
]
}
Переупаковка:
$ rollup -c rollup.plugin.config.js
./src/plugin/main-json.js → ./dist/index-plugin-cjs.js, ./dist/index-plugin-es.js...
[!] Error: Unexpected token (Note that you need rollup-plugin-json to import JSON files)
Вы можете видеть, что rollup.js не поддерживает импорт модуля json по умолчанию, поэтому нам нужно использовать подключаемый модуль json для его поддержки.
Как использовать json-плагин
Загрузите json-плагин:
npm i -D rollup-plugin-json
Измените файл конфигурации:
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
import babel from 'rollup-plugin-babel'
import json from 'rollup-plugin-json'
export default {
input: './src/plugin/main-json.js',
output: [{
file: './dist/index-plugin-cjs.js',
format: 'cjs'
}, {
file: './dist/index-plugin-es.js',
format: 'es'
}],
plugins: [
resolve(),
commonjs(),
babel(),
json()
]
}
Переупаковка:
rollup -c rollup.plugin.config.js
Глядя на исходный код dist/index-plugin-cjs.js, вы можете видеть, что файл json анализируется в объект для обработки:
var name = "rollup-test";
var version = "1.0.0";
var description = "";
var main = "index.js";
var scripts = {
test: "echo \"Error: no test specified\" && exit 1"
};
var author = "";
var license = "ISC";
var devDependencies = {
"@babel/core": "^7.1.6",
"@babel/plugin-external-helpers": "^7.0.0",
"@babel/preset-env": "^7.1.6",
rollup: "^0.67.3",
"rollup-plugin-babel": "^4.0.3",
"rollup-plugin-commonjs": "^9.2.0",
"rollup-plugin-json": "^3.1.0",
"rollup-plugin-node-resolve": "^3.4.0"
};
var dependencies = {
epubjs: "^0.3.80",
loadsh: "^0.0.3",
"sam-test-data": "^0.0.4",
"sam-test-data-cjs": "^0.0.1",
"sam-test-data-es": "^0.0.1",
"sam-test-data-umd": "^0.0.1"
};
var json = {
name: name,
version: version,
description: description,
main: main,
scripts: scripts,
author: author,
license: license,
devDependencies: devDependencies,
dependencies: dependencies
};
console.log(json.name, json.main);
уродовать плагин
Плагин uglify может помочь нам еще больше уменьшить размер кода. Сначала установите плагин:
npm i -D rollup-plugin-uglify
Измените файл конфигурации rollup.js:
import resolve from 'rollup-plugin-node-resolve'
import commonjs from 'rollup-plugin-commonjs'
import babel from 'rollup-plugin-babel'
import json from 'rollup-plugin-json'
import { uglify } from 'rollup-plugin-uglify'
export default {
input: './src/plugin/main.js',
output: [{
file: './dist/index-plugin-cjs.js',
format: 'cjs'
}],
plugins: [
resolve(),
commonjs(),
babel(),
json(),
uglify()
]
}
Здесь следует отметить, что плагин uglify не поддерживает модули ES и синтаксис ES6, поэтому его можно запаковать только в код формата, отличного от ES.Если встречается синтаксис ES6, произойдет ошибка:
$ rollup -c rollup.plugin.config.js
./src/plugin/main.js → ./dist/index-plugin-cjs.js, ./dist/index-plugin-es.js...
19 | var main = random;
20 |
> 21 | export default main;
| ^ Unexpected token: keyword (default)
[!] (uglify plugin) Error: Unexpected token: keyword (default)
Итак, здесь мы используем sam-test-data для тестирования, потому что этот модуль использует для компиляции babel, а некоторые другие модули не поддерживают uglify (поскольку несколько других модулей используют const, const также является функцией ES6, которую uglify не поддерживает), поэтому, когда вы пишете собственную библиотеку классов, вам следует обратить внимание на использование плагина babel для компиляции. Переупаковка после завершения настройки:
$ rollup -c rollup.plugin.config.js
./src/plugin/main.js → ./dist/index-plugin-cjs.js...
created ./dist/index-plugin-cjs.js in 679ms
Посмотреть исходный код dist/index-plugin-cjs.js:
"use strict";var a=Math.floor(10*Math.random()),b=Math.floor(100*Math.random());function random(a){return a&&a%1==0?Math.floor(Math.random()*a):0}var test=Object.freeze({a:a,b:b,random:random});console.log(test);var main=random;module.exports=main;
Видно, что код минимизирован, а размер значительно уменьшен.
rollup.js watch
режим командной строки
Режим просмотра rollup.js поддерживает мониторинг изменений кода. После изменения кода упаковка будет выполняться автоматически, что очень удобно. Метод заключается в добавлении после инструкции по упаковке.--watch
Только что:
$ rollup -c rollup.plugin.config.js --watch
rollup v0.67.1
bundles ./src/plugin/main-json.js → dist/index-plugin-cjs.js, dist/index-plugin-es.js...
created dist/index-plugin-cjs.js, dist/index-plugin-es.js in 24ms
[2018-11-20 22:26:24] waiting for changes...
Режим API
rollup.js позволяет запустить режим просмотра через API.Создайте следующие файлы в корневом каталоге проекта:
- rollup-watch-input-options.js: конфигурация ввода
- rollup-watch-output-options.js: конфигурация вывода
- rollup-watch-options.js: смотреть конфигурацию
- rollup-watch.js: вызовите API rollup.js, чтобы запустить режим просмотра
Чтобы узел мог выполнять нашу программу, была принята спецификация CommonJS, а код rollup-watch-input-options.js выглядит следующим образом:
const json = require('rollup-plugin-json')
const resolve = require('rollup-plugin-node-resolve')
const commonjs = require('rollup-plugin-commonjs')
const babel = require('rollup-plugin-babel')
const uglify = require('rollup-plugin-uglify').uglify
module.exports = {
input: './src/plugin/main.js',
plugins: [
json(),
resolve({
customResolveOptions: {
moduleDirectory: 'node_modules' // 仅处理node_modules内的库
}
}),
babel({
exclude: 'node_modules/**' // 排除node_modules
}),
commonjs(),
uglify() // 代码压缩
]
}
Код rollup-watch-output-options.js выглядит следующим образом:
module.exports = [{
file: './dist/index-cjs.js',
format: 'cjs',
name: 'sam-cjs'
}]
Код rollup-watch-options.js выглядит следующим образом:
module.exports = {
include: 'src/**', // 监听的文件夹
exclude: 'node_modules/**' // 排除监听的文件夹
}
Код rollup-watch.js выглядит следующим образом:
const rollup = require('rollup')
const inputOptions = require('./rollup-watch-input-options')
const outputOptions = require('./rollup-watch-output-options')
const watchOptions = require('./rollup-watch-options')
const options = {
...inputOptions,
output: outputOptions,
watchOptions
} // 生成rollup的options
const watcher = rollup.watch(options) // 调用rollup的api启动监听
watcher.on('event', event => {
console.log('重新打包中...', event.code)
}) // 处理监听事件
// watcher.close() // 手动关闭监听
Начать прослушивание напрямую через узел:
$ node rollup-watch.js
重新打包中... START
重新打包中... BUNDLE_START
重新打包中... BUNDLE_END
重新打包中... END
После этого мы модифицируем исходный код src/plugin/main.js, и rollup.js автоматически упакует код.
Суммировать
В этом руководстве подробно объясняется плагин, механизм встряхивания дерева и режим просмотра rollup.js.
- Плагин rollup.js
- плагин разрешения: интегрировать внешние модули
- Плагин commonjs: поддерживает модули CommonJS.
- Плагин babel: скомпилируйте синтаксис ES6, чтобы браузеры более ранних версий могли его распознать
- плагин json: поддержка модуля json
- uglify: минимальная упаковка кода (модули ES не поддерживаются)
- tree-shaking: поддерживается только модулями ES, что значительно сокращает объем кода
- режим просмотра: поддержка командной строки и режима API, отслеживание изменений кода в режиме реального времени