【rollup】打包特性解析

rollup是什麼

Rollup 是一個 JavaScript 模塊打包器,能夠將小塊代碼編譯成大塊複雜的代碼,例如 library 或應用程序,對代碼模塊採用es6格式javascript

 

特性

  • tree shaking

Rollup靜態分析代碼中的import,並將排除任何未實際使用的代碼,使得不會增長額外的依賴或使項目的大小膨脹。css

而且,這種基於顯式的 import 和 export 語句的方式,它遠比「在編譯後的輸出代碼中,簡單地運行自動 minifier 檢測未使用的變量」更有效html

  • 導入 CommonJS(Importing CommonJS)

經過插件導入已存在的commonJS模塊java

  • 發佈 ES6 模塊(Publishing ES6 Modules)

爲了確保你的 ES6 模塊能夠直接與「運行在 CommonJS(例如 Node.js 和 webpack)中的工具(tool)」使用,你可使用 Rollup 編譯爲 UMD 或 CommonJS 格式,而後在 package.json 文件的 main 屬性中指向當前編譯的版本。若是你的 package.json 也具備 module 字段,像 Rollup 和 webpack 2 這樣的 ES6 感知工具(ES6-aware tools)將會直接導入 ES6 模塊版本。node

 

安裝rollup

  • 全局 npm install -g rollup
  • 項目 npm install --save-dev rollup

安裝完畢後,****rollup -v***查看下是否安裝成功
jquery

 

rollup由淺入深

接下來,咱們用一系列demo',逐級去接觸rollupwebpack

 

demo0-開始使用rollup

1.初始化一個工程,建立一個依賴模塊文件lib.js和入口文件index.js。

// lib.js
export function logA() {
    console.log('function logA called')
}

export function logB() {
    console.log('function logB called')
}
// index.js
import { logA } from './lib'

logA()

2.而後在當前工程下,打開終端,輸入rollup index.js -f es -o dist.js

index.js是咱們的入口文件
dist.js是咱們的輸出文件
-f es 表示--format es,打包輸出格式爲es格式,"output.format", which can be one of "amd", "cjs", "system", "esm", "iife" or "umd"
-o 表示輸出文件的路徑,在 -o 後面跟着的 dist.js 就是咱們要生成的最終打包文件了。
其實這裏原本應該加上一個參數-i,用來表示入口文件的路徑,但rollup是會把沒有加參數的文件默認爲是入口文件,所以咱們在這裏省略了這個參數es6

顯示出這條信息以後,咱們發現目錄下已經多出了一個 dist.js 文件,打開文件,咱們發現裏面的代碼是這樣的web

function logA() {
    console.log('function logA called');
}

logA();

3.此時咱們就已經完成了打包做業,能夠將dist.js引入到HTML文件或是node模塊中了。

3.1 爲了測試下,咱們新建一個index.htmlnpm

<!DOCTYPE html>
<html lang="en">
    <head>
        <title>rollup 打包測試</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
    </head>
    <body>
        <script src="./dist.js"></script>
    </body>
</html>

而後用chorme打開

3.2 用node運行 node dist.js

 

demo1-使用rollup進行模塊化打包

若是在demo0中的index.js文件中把logA()改爲export default logA(),那麼rollup最後的打包結果就會是

function logA() {
    console.log('function logA called');
}

var index = logA();

export default index

顯然這樣的代碼是不能直接在瀏覽器端和node端運行的,咱們須要把原先的ES6模塊轉化成瀏覽器和node支持的形式

那麼咱們先來看下模塊輸出的幾種格式,咱們使用rollup -h查看下

接下來咱們用rollup來打包一下,在demo0中的index.js文件裏將logA()改爲export default logA(),而後npm init初始化一個package.json,並在package.json文件中寫好不一樣模塊的打包命令

"build:amd": "rollup index.js -f amd -o ./dist/dist.amd.js",
"build:cjs": "rollup index.js -f cjs -o ./dist/dist.cjs.js",
"build:es": "rollup index.js -f es -o ./dist/dist.es.js",
"build:iife": "rollup index.js -f iife -n result -o ./dist/dist.iife.js",
"build:umd": "rollup index.js -f umd -n result -o ./dist/dist.umd.js",
"build:all": "npm run build:amd && npm run build:cjs && npm run build:es && npm run build:iife && npm run build:umd"

在這裏咱們發如今設置模塊爲iife(當即執行函數)和umd時,還加上了一個參數-n,這是由於咱們將logA()的結果設置爲模塊的輸出結果,那麼在使用iife和umd時,須要事先設定模塊的名稱,才能讓其餘人經過這個模塊名稱引用到你的模塊的輸出結果。

在命令行中輸入npm run build:all,運行全部打包命令,查看效果

PS: 使用amd模塊打包方式時,若不指定模塊名稱,則會打包成匿名函數,若想打包成一個具名函數,則須要使用-u或--id來指定具名函數名稱。

除了-f以外,還有許多其餘的參數可使用,看到這裏可能有些同窗會以爲麻煩了,這麼多參數用起來好麻煩,每次都要輸一長串的命令,那麼有沒有更好的方法來控制rollup的參數配置呢?

固然有,接下來咱們就嘗試使用配置文件來控制rollup打包。

 

demo2-使用配置文件來進行rollup打包

1.建立一個demo2

沿用以前demo1的內容,咱們在demo2的項目下建立一個文件,取名爲rollup.config.js,這個文件就是rollup的配置文件了,rollup根據配置文件的輸出配置來進行打包,接下來咱們在配置文件中輸入配置代碼:

export default {
    input: 'index.js',
    output: {
        file: 'dist.js',
        format: 'cjs'
    }
};
  • input表示打包的入口文件,
  • output 表示打包輸出 output.file表示輸出文件名,output.format 表示輸出文件模塊格式

PS: 若使用iife或umd模塊打包,須要添加屬性moduleName,用來表示模塊的名稱;若用amd模塊打包,能夠配置amd相關的參數(使用umd模塊模式時,也會使用到amd相關配置參數):

amd: {
    id: 'amd-name',   // amd具名函數名稱
    define: 'def'     // 用來代替define函數的函數名稱
}

在這裏咱們發現配置文件也是使用了ES6語法,這是由於rollup能夠本身處理配置文件,因此可以直接用ES6的模塊輸出(固然,你也能夠選擇使用node的module.exports方式來輸出配置。

2.在package.json文件中編寫npm scripts命令

"build": "rollup -c"

-c這個參數表示使用配置文件來進行打包,若後面沒有指定使用的配置文件路徑,則使用默認的配置文件名稱rollup.config.js。

3.在命令行中輸入npm run build,執行打包,能夠看到生成了打包文件dist.js

'use strict';

function logA() {
    console.log('function logA called');
}

var index = logA();

module.exports = index;

4. 進階:當rollup配置文件最終輸出的不是一個對象而是一個數組時,rollup會把每個數組元素當成一個配置輸出結果,所以能夠在一個配置文件內設置多種輸出配置

例如,咱們添加一個indexB.js文件,在這個文件中咱們將logA替換爲logB,並將rollup配置文件改成:

export default [
    {
        input: 'index.js',
        output: {
            file: 'dist/dist.js',
            format: 'cjs'
        }
    },
    {
        input: 'indexB.js',
        output: {
            file: 'dist/distB.js',
            format: 'cjs'
        }
    }
];

運行打包命令,發如今dist目錄下生成了distA.js和distB.js兩個文件,說明多項配置打包成功。

除了上面這種輸出一個配置數組以外,你還能夠經過配置target屬性來輸出多個打包文件:

export default {
    input: 'index.js',
    output: [
        {
            file: 'dist/dist.es.js',
            format: 'es'
        }, {
            file: 'dist/dist.cjs.js',
            format: 'cjs'
        }, {
            file: 'dist/dist.umd.js',
            name: 'dist_umd',
            format: 'umd'
        }
    ]
}

這樣配置會在dist目錄下面輸出bundle.cjs.js,bundle.umd.js和bundle.es.js三個打包文件,同時umd模塊的名稱會被定義成dist_umd。

 

demo3-監聽文件變化,隨時打包

咱們在開發過程當中,須要頻繁對源文件進行修改,若是每次都本身手動輸一遍打包命令,那真的是要煩死。所以,咱們選擇使用rollup提供的監聽功能,安裝rollup-wacth模塊,再在rollup命令後面加上-w參數,就能讓rollup監聽文件變化,即時打包。

1.新版的rollup已經封裝了watch功能,不須要額外安裝

2.編寫npm scripts:

"watch": "rollup -c -w"

執行npm run watch,看到下面的提示:

好了,這個時候你就能夠隨便修改你的源文件了,rollup會自動爲你打包的。

PS: 如果你不想監聽某些文件,只要在配置文件中加上

watch: {
    exclude: ['path/to/file/which/you/want/to/ignore']
}

就好了,其中的exclude表示你想要忽略的文件的路徑(支持glob模式匹配)

demo4-是時候寫ES6了

ES6能夠說是現代JS開發100%會用到的技術了,rollup雖然支持瞭解析import和export兩種語法,可是卻不會將其餘的ES6代碼轉化成ES5代碼,所以咱們在編寫ES6代碼的時候,須要引入插件來支持ES6代碼的解析。

1.安裝插件和你須要的babel preset:

npm i rollup-plugin-babel @babel/preset-env @babel/core --save-dev

2.建立.babalrc文件:

{
    "presets": [
        [
            "env",
            {
                "modules": false
            }
        ]
    ]
}

之因此使用modules:false這個參數,是由於rollup默認是經過ES6模塊語法來解析文件間的依賴,rollup默認是不支持解析common.js的模塊規範的(怎麼讓rollup支持我會在接下來的demo中講解),所以須要讓babel不轉化模塊相關的語法,否則rollup在使用過程當中會報錯。

3.編寫rollup配置文件:

import babel from 'rollup-plugin-babel';

export default {
    input: 'index.js',
    output: [
        {
            file: 'dist/dist.es.js',
            format: 'es'
        }, {
            file: 'dist/dist.cjs.js',
            format: 'cjs'
        }, {
            file: 'dist/dist.umd.js',
            name: 'dist_umd',
            format: 'umd'
        }
    ],
    plugins: [
        babel({
            exclude: 'node_modules/**'
        })
    ]
}

4. 編寫es6代碼

這裏咱們新建三個文件,兩個類Person和Man和一個入口文件index.js

// Person.js
export default class Person {
    constructor (name, gender = '男') {
        this.name = name
        this.gender = gender
    }

    say () {
        console.log(`個人名字是${this.name},是一個${this.gender}生`)
    }
}
// Man.js
import Person from './Person'

export default class Man extends Person {
    constructor (name) {
        super(name, '男')
    }
}
// index.js
import Man from './Man'

new Man('KainStar').say()

5. 運行npm run build


打開打包後的代碼看一眼,這裏咱們看下dist.es.js

看看打包出來的文件能不能運行,執行node dist/dist.js

 

demo5-解析cjs,打包第三方模塊

有時候咱們會引入一些其餘模塊的文件(第三方的或是本身編寫的),可是這些第三方的模塊爲了可以直接使用,每每不是ES6模塊而是用commonjs的模塊方式編寫的,這個時候咱們須要將commonjs的模塊轉化爲ES6模塊,這樣才能讓rollup進行正確的解析。

1.解析commonjs

解析commonjs須要引入一個rollup插件——rollup-plugin-commonjs

安裝插件

npm i rollup-plugin-commonjs --save-dev
// or
yarn add rollup-plugin-commonjs --dev

2.配置項中配置插件

import commonjs from 'rollup-plugin-commonjs'

export default {
    input: 'index.js',
    output: [{
        file: 'dist/dist.cjs.js',
        name: 'cjs_test',
        format: 'iife'
    }
    ],
    plugins: [
        commonjs()
    ]
}

3. 編寫cjs模塊的文件

// index.js
exports.logA = function logA() {
    console.log('function logA called')
}

exports.logB = function logB() {
    console.log('function logB called')
}

4. 運行npm run build

能夠看到打包成功

5.在打包第三方模塊的過程當中遇到的問題總結

因爲rollup沒法直接解析npm模塊,所以須要引入插件rollup-plugin-node-resolve並配合以前的commonjs插件來解析這些第三方模塊

5.1 安裝插件和第三方模塊

npm i rollup-plugin-node-resolve lodash --save-dev
// or
yarn add rollup-plugin-node-resolve lodash --dev

5.2 在配置文件中配置插件

// rollup.config.sj
import commonjs from 'rollup-plugin-commonjs'
import resolve from 'rollup-plugin-node-resolve'

export default {
    input: 'index.js',
    output: [{
        file: 'dist/dist.cjs.js',
        name: 'cjs_test',
        format: 'iife'
    }
    ],
    plugins: [
        resolve({
            jsnext: true,
            main: true,
            browser: true
        }),
        commonjs()
    ]
}

jsnext表示將原來的node模塊轉化成ES6模塊,
main和browser則決定了要將第三方模塊內的哪些代碼打包到最終文件中。

ps:因爲commonjs和node-resolve中的配置屬性不少,所以不一一解釋,但願瞭解更多的同窗能夠去官方倉庫查看說明。

5.3 編寫index.js

import compact from 'lodash/compact'

const array = [0, 1, false, 2, '', 3]
const compctedArray = compact(array)
console.log(compctedArray)

// 在這裏咱們只引用了lodash中的compact方法,那麼在最終代碼裏,應該也只會添加compact方法的代碼。

5.4 運行npm run build 查看打包結果

確實只添加了compact方法的代碼,而沒有將lodash所有引入。

 

demo6-不要打包到一個文件,爲rollup設置外部模塊和全局變量

在平時的開發中,咱們常常會引入其餘的模塊,可是在使用的時候,咱們又不想把它們打包到一個文件裏,想讓他們做爲單獨的模塊(或文件)來使用,方便瀏覽器端進行緩存,這個時候就須要使用配置文件中的external屬性了

1.咱們在demo5的基礎上,把jquery安裝到第三方模塊中

npm i jquery --save-dev
// or
yarn add jquery --dev

2.將配置文件改爲

import commonjs from 'rollup-plugin-commonjs'
import resolve from 'rollup-plugin-node-resolve'

export default {
    input: 'index.js',
    output: [{
        file: 'dist/dist.cjs.js',
        name: 'cjs_test',
        format: 'iife'
    }],
    external: ['jquery'],
    plugins: [
        resolve({
            jsnext: true,
            main: true,
            browser: true
        }),
        commonjs()
    ]
}

external用來表示一個模塊是否要被當成外部模塊使用,屬性的值能夠是一個字符串數組或一個方法,當傳入的是一個字符串數組時,全部數組內的模塊名稱都會被當成是外部模塊,不會被打包到最終文件中

3. 在index.js中引入jquery

import compact from 'lodash/compact'
import JQuery from 'jquery'

const array = [0, 1, false, 2, '', 3]
const compctedArray = compact(array)
console.log(compctedArray)

4.在這裏咱們把jquery當成一個外部模塊,執行打包命令:

檢查打包出來的文件,咱們發現lodash的compact方法依舊被打包進了最終文件中,可是jquery卻沒有被打包進去,而是以$的全局變量形式被傳入到了當即執行函數中。

在這裏rollup又給咱們輸出了一條提示信息,意思是咱們沒有在配置文件中給外部模塊jquery設置全局變量名稱,所以rollup本身猜想了一個名稱$,當成是依賴的全局變量名。

若是直接使用全局的$的話,可能會由於變量$被其餘引入的代碼覆蓋而報錯,所以咱們要將$替換爲不容易衝突的jQuery變量,在配置文件中添加globals屬性:

import commonjs from 'rollup-plugin-commonjs'
import resolve from 'rollup-plugin-node-resolve'

export default {
    input: 'index.js',
    output: [{
        file: 'dist/dist.cjs.js',
        name: 'cjs_test',
        format: 'iife',
        globals: {
            jquery: 'jQuery'
        }
    }],
    external: ['jquery'],
    plugins: [
        resolve({
            jsnext: true,
            main: true,
            browser: true
        }),
        commonjs()
    ]
}

再次打包結果:

只是提示第三方模塊未使用,實際上咱們確實沒有使用

globals的值是一個對象,key表示使用的模塊名稱(npm模塊名),value表示在打包文件中引用的全局變量名,在這裏咱們就是把jquery模塊的全局變量名設置爲jQuery,從新打包

在從新打包出來的文件中,咱們發現最後傳入的參數已經由$變爲了jQuery,並且rollup也沒有輸出提示信息

demo7-打包node內置模塊

有時候咱們想要在瀏覽器端使用node自帶的一些內置模塊,通常狀況下會使用browserify這個工具來打包,可是browserify打包出來的文件實在太大,所以咱們用rollup選擇性地導入咱們須要的node內置模塊

1.安裝插件

npm i rollup-plugin-node-builtins --save-dev
// or
yarn add rollup-plugin-node-builtins --dev

node-builtins對不一樣的node內置模塊支持不一樣,有些模塊可能須要使用其餘的插件(例如rollup-plugin-node-globals)才能正常打包,具體的支持狀況能夠查看node-builtins的官方倉庫。

2.編寫配置文件

import builtins from 'rollup-plugin-node-builtins'

export default {
    input: 'index.js',
    output: [{
        file: 'dist/dist.cjs.js',
        name: 'cjs_test',
        format: 'iife'
    }],
    plugins: [
        builtins()
    ]
}

3. 編寫入口文件

import { join } from 'path'

const path_base = 'E://node'
const path_joined = join(path_basem, 'bin')
console.log(path_joined)

4. 運行npm run build

在這裏咱們使用node內置的path模塊,運行打包命令,發現dist.js文件中引入了額外的100多行代碼,這100多行代碼就實現了path模塊的join方法供咱們使用。

PS: 我建議,若是不是必要的狀況,最好可以使用其餘人編寫的第三方實現庫或本身造輪子實現,而不是使用node內置的模塊,由於在引用某些模塊時,node-builtins可能會引入過多的代碼,這樣會大大增長最後打包的文件的大小,使用他人的第三方庫或本身的實現可控性更高

 

demo8 配合CDN來使用rollup

有時候咱們可能會使用CDN服務器上的js文件,可是又不想在本地安裝一個相同的模塊(也有可能沒有對應的模塊),可能在版本升級的時候會產生一些問題,這個時候咱們就須要使用rollup的paths屬性了,這個屬性能夠幫助你把依賴的代碼文件地址注入到打包以後的文件裏。

1.編寫配置文件

export default {
    input: 'index.js',
    output: [{
        file: 'dist/dist.amd.js',
        format: 'amd'
    }],
    external: ['jquery'],
    paths: {
        jquery: 'https://cdn.bootcss.com/jquery/3.2.1/jquery.js'
    }
}

在這裏咱們要使用cdn上的jquery文件,paths屬性的值能夠是一個對象或用法與external屬性方法類似的方法(只是返回的不是boolean值而是文件的地址)。若使用對象來表示,則key值爲須要引入的模塊名稱,value值爲對應的文件地址

2. 編寫index.js

import $ from 'jquery'

$('#p').html('rollup 使用paths屬性配合CDN')

3. 運行npm run build

 

demo9 最小化你的代碼

代碼發佈時,咱們常常會把本身的代碼壓縮到最小,以減小網絡請求中的傳輸文件大小

rollup的插件rollup-plugin-uglify就是來幫助你壓縮代碼的,咱們接下來就用這個插件來壓縮一下咱們的代碼

1. 安裝插件

npm i rollup-plugin-uglify --save-dev
// or
yarn add rollup-plugin-uglify --dev

2. 配置

import { uglify } from 'rollup-plugin-uglify'

export default {
    input: 'index.js',
    output: [{
        file: 'dist/dist.js',
        format: 'iife',
        name: 'test'
    }],
    plugins: [
        uglify()
    ]
}

3. 隨便寫點index.js

4. npm run build

運行打包命令,查看dist.js文件,發現代碼已經被壓縮了

可是,壓縮過的代碼在debug時會帶來很大的不便,所以咱們須要在壓縮代碼的同時生成一個sourceMap文件

幸運的是,rollup本身就支持sourceMap文件的生成,不須要咱們去引入其餘插件,只須要在配置文件的對應output中加上:

import { uglify } from 'rollup-plugin-uglify'

export default {
    input: 'index.js',
    output: [{
        file: 'dist/dist.js',
        format: 'iife',
        name: 'test',
        sourcemap: true
    }],
    plugins: [
        uglify()
    ]
}

從新打包,咱們發現不只生成了dist.js.map文件,並且dist文件最後加上了一行//# sourceMappingURL=dist.js.map,而且在瀏覽器中能夠正確加載源文件

PS: 如果將sourcemap屬性的值設置爲inline,則會將sourceMap的內容添加到打包文件的最後

 

demo10 爲你的代碼添eslint檢查

在大型工程的團隊開發中,咱們須要保證團隊代碼風格的一致性,所以須要引入eslint,並且在打包時須要檢測源文件是否符合eslint設置的規範,如果不符合則拋出異常並中止打包。在這裏咱們使用rollup的eslint插件rollup-plugin-eslint:

1.安裝插件

npm i eslint rollup-plugin-eslint --save-dev
// or
yarn add eslint rollup-plugin-eslint --dev

2. 編寫eslint配置文件.eslintrc

{
    "env": {
        "browser": true,
        "commonjs": true,
        "es6": true,
        "node": true
    },
    "parserOptions": {
        "ecmaFeatures": {
            "jsx": false
        },
        "sourceType": "module"
    },
    "rules": {
        "semi": [
            "error",
            "never"
        ]
    }
}

3.在這裏咱們強制要求不使用分號,而後在源文件中加上一個分號

// src/index.js
console.log(1);

4.編寫配置文件

import eslint from 'rollup-plugin-eslint';

export default {
    input: 'src/index.js',
    output: [{
        file: 'dist/dist.js',
        format: 'iife',
        name: 'test',
        sourcemap: true
    }],
    plugins: [
        eslint.eslint({
            throwOnError: true,
            throwOnWarning: true,
            include: ['src/**'],
            exclude: ['node_modules/**']
        })
    ]
}

throwOnError和throwOnWarning設置爲true時,若是在eslint的檢查過程當中發現了error或warning,就會拋出異常,阻止打包繼續執行(若是設置爲false,就只會輸出eslint檢測結果,而不會中止打包)

5. 執行打包命令,發現eslint在輸出了檢查結果以後拋出了異常,並且dist.js文件也沒有生成

刪除index.js文件中的分號,從新打包,發現打包成功

6.進階:

在平時的開發過程當中,咱們常常會使用IDE或編輯器的eslint插件,以便提前發現問題,可是有時候這些插件會去檢查打包完的文件,致使你的提示框裏一直會有eslint檢測到錯誤的消息

咱們如今有兩種解決方案:

  • 一是建立一個.eslintignore文件,將打包文件加進去,讓eslint忽略這個文件
  • 還有一種就是讓rollup在打包文件的開始和最後自動生成註釋來阻止eslint檢測代碼,使用這種方法時,須要使用rollup配置文件的兩個屬性:banner和footer,這兩個屬性會在生成文件的開頭和結尾插入一段你自定義的字符串。咱們利用這個屬性,在打包文件的開頭添加/eslint-disable /註釋,讓eslint不檢測這個文件。
    添加banner和footer屬性
banner: '/*eslint-disable */'

從新打包,咱們發現打包文件的開頭被插入了這段註釋字符串,並且eslint插件也不報dist.js文件的錯了

 

demo11 控制開發環境和生產環境下的配置

1.配置文件的開發/生產環境配置

有時候咱們會須要區分開發環境和生產環境,針對不一樣的打包要求輸出不一樣的打包配置,可是咱們又不想寫rollup.config.dev.js和rollup.config.prod.js兩個文件,由於可能二者之間的區別只是一個uglify插件。

所以,咱們就須要用變量來控制配置文件的輸出內容,rollup命令行給咱們提供了一個設置環境變量的參數--environment,在這個參數後面加上你須要設置的環境變量,不一樣變量間用逗號分隔,用冒號後面的字符串表示對應變量的值(若不加冒號,則默認將值設爲字符串true):

在package.json文件中編寫對應的npm scripts命令:

"dev": "rollup -c --environment NODE_ENV:development",
"build": "rollup -c --environment NODE_ENV:production"

最後修改咱們的rollup配置文件

import { uglify } from 'rollup-plugin-uglify'

let isProd = process.env.NODE_ENV === 'production'

// 通用的插件
const basePlugins = []
// 開發環境須要使用的插件
const devPlugins = []
// 生產環境須要使用的插件
const prodPlugins = [uglify()]

let plugins = [...basePlugins].concat(isProd ? prodPlugins : devPlugins)
let outputFilePath = isProd ? './dist/dist.min.js' : './dist/dist.js'

export default {
    input: 'src/index.js',
    output: [{
        file: outputFilePath,
        format: 'iife',
        name: 'test',
        sourcemap: isProd
    }],
    plugins: plugins
}

咱們分別運行兩個npm scripts命令,查看打包的結果:

2. 源文件開發/生產環境信息注入

有時候須要將生產環境信息添加到源文件裏,這個時候就須要使用rollup的配置屬性intro和outro了

若是說banner和footer是在文件開始和結尾添加字符串,那麼intro和outro就是在被打包的代碼開頭和結尾添加字符串了,以iife模式來舉例,若是咱們配置了這四個屬性,那麼輸出結果就會是:

// banner字符串
(function () {
'use strict';
// intro字符串

// 被打包的代碼

// outro字符串
}());
// footer字符串

下面咱們實際使用一下,在index.js文件里加上一段須要依賴的代碼

if (DEVELOPMENT) {
  console.log('development')
} else {
  console.log('production')
}

而後修改配置文件

import { uglify } from 'rollup-plugin-uglify'

let isProd = process.env.NODE_ENV === 'production'

// 通用的插件
const basePlugins = []
  // 開發環境須要使用的插件
const devPlugins = []
  // 生產環境須要使用的插件
const prodPlugins = [uglify()]

let plugins = [...basePlugins].concat(isProd ? prodPlugins : devPlugins)
let outputFilePath = isProd ? './dist/dist.min.js' : './dist/dist.js'

export default {
  input: 'src/index.js',
  output: [{
    file: outputFilePath,
    format: 'iife',
    name: 'test',
    sourcemap: isProd,
    intro: 'const DEVELOPMENT = ' + !isProd
  }],
  plugins: plugins
}

接着運行npm run dev,查看打包後的文件以下】

3. 源文件開發/生產環境信息替換

有時候咱們會把開發/生產環境的信息直接寫在源文件裏面,這個時候用intro來注入代碼的方式就不適合了。這個時候咱們就須要使用rollup-plugin-replace插件來對源代碼的變量值進行替換:

在上面這個文件的基礎上,先把intro給註釋了,而後

npm i rollup-plugin-replace --save-dev
// or
yarn add rollup-plugin-replace --dev

接着,更改下配置,

import { uglify } from 'rollup-plugin-uglify'
import replace from 'rollup-plugin-replace'

let isProd = process.env.NODE_ENV === 'production'

// 通用的插件
const basePlugins = [replace({
  DEVELOPMENT: !isProd
})]

// 開發環境須要使用的插件
const devPlugins = []

// 生產環境須要使用的插件
const prodPlugins = [uglify()]

let plugins = [...basePlugins].concat(isProd ? prodPlugins : devPlugins)
let outputFilePath = isProd ? './dist/dist.min.js' : './dist/dist.js'

export default {
  input: 'src/index.js',
  output: [{
    file: outputFilePath,
    format: 'iife',
    name: 'test',
    sourcemap: isProd,
    // intro: 'const DEVELOPMENT = ' + !isProd
  }],
  plugins: plugins
}

接着,打包npm run dev,查看打包結果

 

demo12 使用rollup的API

有時候咱們會須要在打包的先後執行一些其餘的代碼,可是又不想引入其餘構建工具(例如gulp),那麼就可使用rollup提供的node API來編寫你本身的打包流程。

rollup模塊只提供了一個rollup函數,這個函數的參數和咱們編寫配置文件時導出的參數不一樣,減小了不少配置屬性,留下來的主要是一些輸入相關的配置。(具體的配置屬性能夠查看rollup wiki的javascript API一節)

執行這個函數返回的是一個Promise,而且在then方法中提供一個bundle對象做爲參數,這個對象保存了rollup對源文件編譯一次以後的結果,並且提供了generate和write兩個方法

  • write方法提供了編譯並將打包結果輸出到文件裏的功能,返回的是一個沒有參數的Promise,可讓你自定義接下來執行的代碼
  • generate方法是隻提供了編譯的功能,返回一個Promise,這個Promise有一個對象參數,包含了code(編譯完以後的代碼)和map(分析出來的sourceMap對象)兩個屬性,通常用在插件開發中

在這裏咱們只使用write方法來編寫一個爲全部模塊類型打包,並輸出打包完畢提示的文件,至於generate的使用方法咱們會放在編寫插件一節中介紹。

const rollup = require('rollup').rollup

rollup({
    entry: 'index.js'
}).then(bundle => {

    // 保存全部Promise的列表
    let writePromiseList = []
    // 聲明全部須要打包的模塊類型
    let moduleTypesList = ['es','cjs','amd','umd','iife']

    moduleTypesList.forEach(function(moduleType) {
        writePromiseList.push(bundle.write({
            dest: './dist/dist.' + moduleType + '.js',
            format: moduleType,
            sourceMap: true
        }))
    })

    return Promise.all(writePromiseList)

}).then(() => {
    console.log('所有模塊格式打包完畢')
    // 其餘代碼
})

將package.json文件內的npm scripts命令添加

"rollup": "node rollup.js"

執行npm run rollup

 

demo13 除了打包JS,咱們還能……

一個web項目內確定不會只有js文件,還有css、html(也多是模板文件)和其餘類型的文件,那麼咱們在打包的時候能不能把這些文件一塊兒打包呢?

咱們須要區分一下,在這裏的打包有兩種意思,

  • 一種是讓這些文件能夠像JS文件同樣,在源代碼中被import並使用;
  • 還有一種是經過在源文件中import這些文件,最後將它們合併到一塊兒並導出到一個最終文件內。

不一樣的rollup插件有不一樣的效果,在使用的時候必定要查看插件的相關說明

安裝插件

npm i rollup-plugin-scss --save-dev
// or
yarn add rollup-plugin-scss --dev

編寫配置文件

import { uglify } from 'rollup-plugin-uglify'
import scss from 'rollup-plugin-scss'

let isProd = process.env.NODE_ENV === 'production'

// 通用的插件
const basePlugins = [scss({
  output: {
    file: './dist/css/style.css'
  }
})]

// 開發環境須要使用的插件
const devPlugins = []

// 生產環境須要使用的插件
const prodPlugins = [uglify()]

let plugins = [...basePlugins].concat(isProd ? prodPlugins : devPlugins)
let outputFilePath = isProd ? './dist/dist.min.js' : './dist/dist.js'

export default {
  input: 'src/index.js',
  output: [{
    file: outputFilePath,
    format: 'iife',
    name: 'test',
    sourcemap: isProd
  }],
  plugins: plugins
}

編寫src/index.js

import './scss/text.scss'
import './scss/bg.scss'

var html = `
    <div class="bg-blue">
        <p class="text-white">測試文字</p>
    </div>
`
document.body.innerHTML = html

編寫src/scss/text.scss

$white: #fff;
.text-white {
  color: $white;
}

編寫src/scss/bg.scss

$blue: #69c4eb;
.bg-blue {
  background-color: $blue
}

執行打包命令,查看效果

相關文章
相關標籤/搜索