深刻学习rollup来进行打包

深刻学习rollup来进行打包css

阅读目录html

一:什么是Rollup?vue

  rollup是一款用来es6模块打包代码的构建工具(支持css和js打包)。当咱们使用ES6模块编写应用或者库时,它能够打包成一个单独文件提供浏览器和Node.js来使用。
它的优势有以下
  1. 能组合咱们的脚本文件。
  2. 移除未使用的代码(仅仅使用ES6语法中)。
  3. 在浏览器中支持使用 Node modules。
  4. 压缩文件代码使文件大小尽量最小化。node

Rollup最主要的优势是 它是基于ES2015模块的,相比于webpack或Browserify所使用的CommonJS模块更加有效率,由于Rollup使用一种叫作
tree-shaking的特性来移除模块中未使用的代码,这也就是说当咱们引用一个库的时候,咱们只用到一个库的某一段的代码的时候,它不会把全部的代码打包进来,而仅仅打包使用到的代码(webpack2.0+貌似也引入了tree-shaking)。jquery

注意:Rollup只会在ES6模块中支持tree-shaking特性。目前按照CommonJS模块编写的jquery不能被支持tree-shaking.webpack

rollup 的应用场景git

如今目前流行的打包有 gulp 和 webpack,那么与前面两个对比,我以为rollup更适合打包js库,可是对于打包一个项目的整个应用的话,我到以为webpack更适合,好比打包一些图片,字体等资源文件的时候,webpack很适合,目前貌似没有看到rollup能够作到这些。
之因此我来研究rollup,是由于最近在看vuex的源码的时候,看到它的js库就是使用rollup来进行打包的。es6

二:如何使用Rollup来处理并打包JS文件?github

2-1 安装Rollup并建立配置文件,经过以下命令安装:
      进入项目根目录后,运行命令: npm install --save-dev rollupweb

2-2 在项目的根目录下新建一个新文件 rollup.config.js, 以后再在文件中添加以下代码:

export default {
  input: './src/main.js',
  output: {
    file: './dist/js/main.min.js',
    format: 'iife'
  }
}

下面再来了解一下各个配置的含义:
input: rollup先执行的入口文件。
output:rollup 输出的文件。
output.format: rollup支持的多种输出格式(有amd,cjs, es, iife 和 umd, 具体看 http://www.cnblogs.com/tugenhua0707/p/8150915.html)
sourceMap —— 若是有 sourcemap 的话,那么在调试代码时会提供很大的帮助,这个选项会在生成文件中添加 sourcemap,来让事情变得更加简单。

咱们在package.json代码下 添加以下脚本。

"scripts": {
  "build": "rollup -c"
}

所以咱们只要在命令行中 输入命令:npm run build 便可完成打包;

咱们再看下各个文件下的代码:

src/js/a.js 代码以下:

export function a(name) {
  const temp = `Hello, ${name}!`;
  return temp;
}
export function b(name) {
  const temp = `Later, ${name}!`;
  return temp;
}

src/js/b.js代码以下:

/**
 * Adds all the values in an array.
 * @param  {Array} arr an array of numbers
 * @return {Number}    the sum of all the array values
 */
const addArray = arr => {
  const result = arr.reduce((a, b) => a + b, 0);
  return result;
};
export default addArray;

src/main.js代码以下:

import { a } from './js/a';
import addArray from './js/b';

const res1 = a('kongzhi');
const res2 = addArray([1, 2, 3, 4]);

console.log(res1);
console.log(res2);

最终会在项目的根目录下生成文件 dist/js/main.min.js, 代码以下:

(function () {
'use strict';

function a(name) {
  const temp = `Hello, ${name}!`;
  return temp;
}

/**
 * Adds all the values in an array.
 * @param  {Array} arr an array of numbers
 * @return {Number}    the sum of all the array values
 */
const addArray = arr => {
  const result = arr.reduce((a, b) => a + b, 0);
  return result;
};

const res1 = a('kongzhi');
const res2 = addArray([1, 2, 3, 4]);

console.log(res1);
console.log(res2);

}());

如上能够看到 在 src/js/a.js 下的 b函数没有被使用到,因此打包的时候没有被打包进来。

注意:在上面代码打包后,只有现代浏览器会正常工做,若是要让不支持ES2015的旧版本浏览器下也正常工做的话,咱们须要添加一些插件。

三:设置Babel来使旧浏览器也支持ES6的代码

如上打包后的代码,咱们能够在现代浏览器下运行了,可是若是咱们使用老版本的浏览器的话,就会产生错误。幸运的是,Babel已经提供了支持。
咱们首先须要安装一些依赖项以下命令:

npm install --save-dev 
babel-core babel-preset-env babel-plugin-external-helpers 
babel-plugin-transform-runtime babel-preset-stage-2 
babel-register rollup-plugin-babel

注意:Babel preset 是一个有关Babel插件的集合,它会告诉Babel咱们须要转译什么。

3.2 建立 .babelrc文件

接下来须要在项目的根目录下建立 .babelrc的新文件了,它内部添加以下JSON代码:

{
  "presets": [
    ["env", {
      "modules": false,
      "targets": {
        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
      }
    }],
    "stage-2"
  ],
  "plugins": ["transform-runtime", "external-helpers"]  // 配置runtime,不设置会报错
}

它会告诉Babel应该使用哪一种preset来转译代码。

所以咱们再更新下 rollup.config.js,咱们须要Babel插件,将它添加到一个新的配置选项plugins中,他会管控一个数组形式的插件列表,代码以下:

// Rollup plugins
import babel from 'rollup-plugin-babel';

export default {
  input: './src/main.js',
  output: {
    file: './dist/js/main.min.js',
    format: 'iife'
  },
  plugins: [
    babel({
      exclude: 'node_modules/**'  // 排除node_module下的全部文件
    })
  ]
}

为了不转译第三方脚本,咱们须要设置一个 exclude 的配置选项来忽略掉 node_modules 目录下的全部文件。安装完成后,咱们从新运行命令;而后打包后代码变成以下:

(function () {
'use strict';

function a(name) {
  var temp = "Hello, " + name + "!";
  return temp;
}

/**
 * Adds all the values in an array.
 * @param  {Array} arr an array of numbers
 * @return {Number}    the sum of all the array values
 */
var addArray = function addArray(arr) {
  var result = arr.reduce(function (a, b) {
    return a + b;
  }, 0);
  return result;
};

var res1 = a('kongzhi');
var res2 = addArray([1, 2, 3, 4]);

console.log(res1);
console.log(res2);

}());

咱们对比下代码,能够看到 addArray 的箭头函数解析成真正的函数了。 在转译运行完成后,代码也差很少同样的,只是代码已经支持
了IE9以前的浏览器了。

注意: Babel也提供了 babel-polyfill, 也可让IE8以前的浏览器可以顺利执行。

四:添加一个debug包来记录日志

 为了查看日志,咱们将在代码中添加一个debug包来记录下日志信息。经过以下命令安装:

npm install --save debug

而后咱们能够在 src/main.js中,添加一些简单的日志记录:以下代码:

import { a } from './js/a';
import addArray from './js/b';
import debug from 'debug';
const log = debug('app:log');

// Enable the logger.
debug.enable('*');
log('Logging is enabled!');

const res1 = a('kongzhi');
const res2 = addArray([1, 2, 3, 4]);

// Print the results on the page.
const printTarget = document.getElementsByClassName('debug__output')[0];

printTarget.innerText = `sayHelloTo('Jason') => ${res1}\n\n`;
printTarget.innerText += `addArray([1, 2, 3, 4]) => ${res2}`;

index.html 代码变成以下:

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport"
        content="width=device-width,minimum-scale=1,initial-scale=1">
  <title>Learning Rollup</title>
</head>
<body>

  <h1>Learning Rollup</h1>
  <p>
    Let’s learn how to use <a href="http://rollupjs.org/">Rollup</a>.
  </p>

  <!-- JS-generated output will be added here. -->
  <pre class="debug"><code class="debug__output"></code></pre>

  <!-- This is the bundle generated by rollup.js -->
  <script src="./dist/js/main.min.js"></script>

</body>
</html>

而后咱们直接访问index.html后,浏览器控制台报错了,错误信息以下:
Uncaught ReferenceError: debug is not defined,而后咱们能够继续查看,打包后的main.min.js的代码变为以下:

(function (debug) {
'use strict';

debug = debug && debug.hasOwnProperty('default') ? debug['default'] : debug;

function a(name) {
  var temp = "Hello, " + name + "!";
  return temp;
}

/**
 * Adds all the values in an array.
 * @param  {Array} arr an array of numbers
 * @return {Number}    the sum of all the array values
 */
var addArray = function addArray(arr) {
  var result = arr.reduce(function (a, b) {
    return a + b;
  }, 0);
  return result;
};

var log = debug('app:log');

// Enable the logger.
debug.enable('*');
log('Logging is enabled!');

var res1 = a('kongzhi');
var res2 = addArray([1, 2, 3, 4]);

// Print the results on the page.
var printTarget = document.getElementsByClassName('debug__output')[0];

printTarget.innerText = 'sayHelloTo(\'Jason\') => ' + res1 + '\n\n';
printTarget.innerText += 'addArray([1, 2, 3, 4]) => ' + res2;

}(debug));

也就是说 浏览器报错是由于打包后的debug是 undefined,这是由于通常的状况下,第三方node模块并不会被Rollup正确加载。
Node模块使用的是CommonJS, 它不会被Rollup兼容所以不能直接被使用,为了解决这个问题,咱们须要添加一些插件来
处理Node依赖和CommonJS模块。
为了解决上面的两个问题,咱们须要在Rollup中添加以下两个插件:
1. rollup-plugin-node-resolve 该插件会容许加载在 node_modules中的第三方模块。
2. rollup-plugin-commonjs 它会将CommonJS模块转换为ES6来为Rollup得到兼容。

所以以下命令便可安装:

npm install --save-dev rollup-plugin-node-resolve rollup-plugin-commonjs

而后咱们继续更新下 rollup.config.js 代码以下:

// Rollup plugins
import babel from 'rollup-plugin-babel';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import json from 'rollup-plugin-json';

export default {
  input: './src/main.js',
  output: {
    file: './dist/js/main.min.js',
    format: 'iife'
  },
  plugins: [
    resolve({
      jsnext: true,  // 该属性是指定将Node包转换为ES2015模块
      // main 和 browser 属性将使插件决定将那些文件应用到bundle中
      main: true,  // Default: true 
      browser: true // Default: false
    }),
    commonjs(),
    json(),
    babel({
      exclude: 'node_modules/**'  // 排除node_modules 下的文件
    })
  ]
}

到目前为止一切顺利,可是当咱们运行index.html时候, rollup 时咱们会获得一个日志信息:

在控制台以下日志信息:
app:log Logging is enabled! +0ms

index.html 页面上显示以下:

Learning Rollup
Let’s learn how to use Rollup.

sayHelloTo('Jason') => Hello, kongzhi!

addArray([1, 2, 3, 4]) => 10

如上代码,咱们看到引入了 rollup-plugin-json 插件了,该插件的做用是读取json信息的,好比我读取package.json的信息:

而后我把main.js中引入对应代码。代码以下:

import { a } from './js/a';
import addArray from './js/b';
import debug from 'debug';

// 添加json
import pkg from '../package.json';
console.log( `running version ${pkg.version}` ); // 控制台输出 running version 1.0.0

const log = debug('app:log');

// Enable the logger.
debug.enable('*');
log('Logging is enabled!');

const res1 = a('kongzhi');
const res2 = addArray([1, 2, 3, 4]);

// Print the results on the page.
const printTarget = document.getElementsByClassName('debug__output')[0];

printTarget.innerText = `sayHelloTo('Jason') => ${res1}\n\n`;
printTarget.innerText += `addArray([1, 2, 3, 4]) => ${res2}`;

在控制台输出以下信息:
控制台输出 running version 1.0.0

五:添加插件来替代环境变量

 环境变量能为咱们的开发流程提供很大的帮助,咱们能够经过它来执行关闭或开启日志,注入开发环境脚本等功能。
所以咱们能够在main.js中添加基础配置的ENV。让咱们添加一个环境变量来使咱们的日志脚本只在非 production环境下才会执行
。以下main.js代码:

import { a } from './js/a';
import addArray from './js/b';
import debug from 'debug';

// 添加json
import pkg from '../package.json';
console.log( `running version ${pkg.version}` ); // 控制台输出 running version 1.0.0

const log = debug('app:log');

// 若是是正式环境的话,不输出日志信息
if (ENV !== 'production') {
  // Enable the logger.
  debug.enable('*');
  log('Logging is enabled!');
} else {
  debug.disable();
}

const res1 = a('kongzhi');
const res2 = addArray([1, 2, 3, 4]);

// Print the results on the page.
const printTarget = document.getElementsByClassName('debug__output')[0];

printTarget.innerText = `sayHelloTo('Jason') => ${res1}\n\n`;
printTarget.innerText += `addArray([1, 2, 3, 4]) => ${res2}`;

而后打包完成后,在浏览器查看 发现报错了,以下错误信息:
Uncaught ReferenceError: ENV is not defined
这也很正常,由于咱们并无定义它,如今咱们还须要一个插件来将咱们的环境变量用到bundle中。

5-1 先安装 rollup-plugin-replcae,该插件是一个用来查找和替换的工做,咱们只须要找到目前的环境变量而且使用实际
的值替代就能够了。先安装以下:
npm install --save-dev rollup-plugin-replace

而后咱们再来更新一下 rollup.config.js, 配置是咱们能够添加一个 key:value 的配对表,key值是准备被替换的键,而value是将要被替换的值。

// Rollup plugins
import babel from 'rollup-plugin-babel';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import json from 'rollup-plugin-json';
import replace from 'rollup-plugin-replace';

export default {
  input: './src/main.js',
  output: {
    file: './dist/js/main.min.js',
    format: 'iife'
  },
  plugins: [
    resolve({
      jsnext: true,  // 该属性是指定将Node包转换为ES2015模块
      // main 和 browser 属性将使插件决定将那些文件应用到bundle中
      main: true,  // Default: true 
      browser: true // Default: false
    }),
    commonjs(),
    json(),
    babel({
      exclude: 'node_modules/**'  // 排除node_modules 下的文件
    }),
    replace({
      ENV: JSON.stringify(process.env.NODE_ENV || 'development')
    })
  ]
}

当咱们如今运行 npm run build 的时候仍是有日志信息的,由于默认的环境就是 development, 可是当咱们在命令
行中使用以下命令:`NODE_ENV=production ./node_modules/.bin/rollup -c`(mac系统下的命令), 而后打包
后,刷新浏览器 就不会有日志记录信息了。
注意:在winodw环境下,运行以下命令: SET NODE_ENV=production ./node_modules/.bin/rollup -c

六:添加 UglifyJS来压缩咱们js的代码

 安装插件 rollup-plugin-uglify

命令以下安装:
npm install --save-dev rollup-plugin-uglify

再在 rollup.config.js 配置代码,为了在开发中使代码更具可读性,咱们只在生产环境压缩代码:
rollup.config.js配置代码以下:

// Rollup plugins
import babel from 'rollup-plugin-babel';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import json from 'rollup-plugin-json';
import replace from 'rollup-plugin-replace';
import uglify from 'rollup-plugin-uglify';

export default {
  input: './src/main.js',
  output: {
    file: './dist/js/main.min.js',
    format: 'iife'
  },
  plugins: [
    resolve({
      jsnext: true,  // 该属性是指定将Node包转换为ES2015模块
      // main 和 browser 属性将使插件决定将那些文件应用到bundle中
      main: true,  // Default: true 
      browser: true // Default: false
    }),
    commonjs(),
    json(),
    babel({
      exclude: 'node_modules/**'  // 排除node_modules 下的文件
    }),
    replace({
      ENV: JSON.stringify(process.env.NODE_ENV || 'development')
    }),
    (process.env.NODE_ENV === 'production' && uglify())
  ]
}

当咱们在mac系统下运行命令 `NODE_ENV=production ./node_modules/.bin/rollup -c` 后,代码被压缩了,当咱们运行
npm run build 的时候,代码未被压缩。

七:监听文件变化的插件 --- rollup-watch

以下安装命令:
npm install --save-dev rollup-watch

而后在package.json 中设置 scripts属性便可:

"scripts": {
  "dev": "rollup -c -w",
  "build": "rollup -c"
}

当咱们在 src/main.js 代码下 加入一句代码后 : console.log(1122); 而后在浏览器下刷新下便可在控制台能够看到打印输出 1122这样的就能够监听到了。不须要从新打包便可。

八:开启本地服务的插件 --- rollup-plugin-serve

 安装命令以下:

npm install --save-dev rollup-plugin-serve

在rollup.config.js 配置代码以下:

// Rollup plugins
import babel from 'rollup-plugin-babel';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import json from 'rollup-plugin-json';
import replace from 'rollup-plugin-replace';
import uglify from 'rollup-plugin-uglify';
import serve from 'rollup-plugin-serve';
export default {
  input: './src/main.js',
  output: {
    file: './dist/js/main.min.js',
    format: 'iife'
  },
  plugins: [
    resolve({
      jsnext: true,  // 该属性是指定将Node包转换为ES2015模块
      // main 和 browser 属性将使插件决定将那些文件应用到bundle中
      main: true,  // Default: true 
      browser: true // Default: false
    }),
    commonjs(),
    json(),
    babel({
      exclude: 'node_modules/**'  // 排除node_modules 下的文件
    }),
    replace({
      ENV: JSON.stringify(process.env.NODE_ENV || 'development')
    }),
    (process.env.NODE_ENV === 'production' && uglify()),
    serve({
      open: true, // 是否打开浏览器
      contentBase: './', // 入口html的文件位置
      historyApiFallback: true, // Set to true to return index.html instead of 404
      host: 'localhost',
      port: 10001
    })
  ]
}

而后重启命令 npm run build 就能够会自动打开 http://localhost:10001/ 页面了。
注意: 这边port配置的端口号是五位数,不是四位数。

九:实时刷新页面 --- rollup-plugin-livereload

命令安装以下:
npm install --save-dev rollup-plugin-livereload

注入LiveReload脚本
在LiveReload工做前,须要向页面中注入一段脚本用于和LiveReload的服务器创建链接。
在src/main.js 中加入以下一段代码:

// Enable LiveReload
document.write(
  '<script src="http://' + (location.host || 'localhost').split(':')[0] +
  ':35729/livereload.js?snipver=1"></' + 'script>'
);

src/main.js全部代码以下:

import { a } from './js/a';
import addArray from './js/b';
import debug from 'debug';

// 添加json
import pkg from '../package.json';
console.log( `running version ${pkg.version}` ); // 控制台输出 running version 1.0.0

const log = debug('app:log');
// 若是不是正式环境的话,不输出日志信息
if (ENV !== 'production') {
  // Enable the logger.
  debug.enable('*');
  log('Logging is enabled!');
  // Enable LiveReload
  document.write(
    '<script src="http://' + (location.host || 'localhost').split(':')[0] +
    ':35729/livereload.js?snipver=1"></' + 'script>'
  );
} else {
  debug.disable();
}

const res1 = a('kongzhi');
const res2 = addArray([1, 2, 3, 4]);
console.log(1122)
// Print the results on the page.
const printTarget = document.getElementsByClassName('debug__output')[0];

printTarget.innerText = `sayHelloTo('Jason') => ${res1}\n\n`;
printTarget.innerText += `addArray([1, 2, 3, 4]) => ${res2}`;

运行 LiveReload
LiveReload安装好而且脚本注入到文档中后,咱们能够运行它去监听build目录:
以下命令:
./node_modules/.bin/livereload 'build/'

运行完成后 发现报错了 Error: listen EADDRINUSE :::35729;经过百度才发现端口被占用了,须要换端口,所以我直接把这个进程杀掉不就能够了,
首先咱们先使用以下命令来查看下进程:
lsof -n -i4TCP:35729
看到信息以下:

COMMAND  PID     USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
node    1452 tugenhua   15u  IPv6 0xb0e27d409cc55a1b      0t0  TCP *:35729 (LISTEN)

运行以下命令杀掉:

kill -9 1452
再在命令行输入 ./node_modules/.bin/livereload 'src/' 便可看到以下:

$ ./node_modules/.bin/livereload 'src/'
Starting LiveReload v0.6.3 for /Users/tugenhua/我的demo/vue1204/rollup-build/src on port 35729.

注意:./node_modules/.bin/livereload 'src/' 这句代码的含义是 监听src文件夹的文件,所以index.html内会
监听到,咱们能够打开 src/index.html后,而后在index.html修改内容后,保存一下就能够看到页面会自动刷新内容了。

如上虽然改变 src/index.html的内容后会自动刷新页面,可是感受每次 都须要输入 ./node_modules/.bin/livereload 'src/' 这么一段命令,有点麻烦,所以咱们能够在 package.json 脚本中来简化这个过程,在package.json下scripts加上以下代码:

"scripts": {
  "dev": "rollup -c -w",
  "build": "rollup -c",
  "reload": "livereload 'src/'"
}, 

当咱们在命令行中 运行 npm run reload 也能够监听到了。可是咱们监听不到 src/js 或 src/css 下的文件的变化,
由于它不会自动打包,而只是监听src下的文件变化而已。可是咱们又不能同时打开 watcher 和 Livereload,会报错端口被占用的状况。
所以咱们须要看第10条来解决这个问题哦;

十. 安装同时运行watcher 和 Livereload的工具

 为了能同时执行 Rollup和LiveReload, 咱们须要使用一个叫作 npm-run-all 的工具。它的含义是一个终端能够执行多个任务。

安装命令以下:
npm install --save-dev npm-run-all

而后咱们要在package.json中再加入一条调用npm-run-all的脚本。在scripts代码块内,添加以下内容:

"scripts": {
  "dev": "rollup -c -w",
  "build": "rollup -c",
  "reload": "livereload 'src/'",
  "watch": "npm-run-all --parallel dev"
},

watch 就是新增的。所以咱们能够在终端运行 npm run watch命令了,而后刷新浏览器(http://localhost:10002/src/index.html),改变一下js或者css,浏览器会自动加载更新后的代码了。

十一. rollup+PostCSS打包样式文件并添加 LiveReload

 1. 在main.js中加载样式: 在main.js 中加入以下代码:

// Import styles (automatically injected into <head>).
import './css/index.css';
全部的代码以下:
import './css/index.css';

import { a } from './js/a';
import addArray from './js/b';
import debug from 'debug';

// 添加json
import pkg from '../package.json';
console.log( `running version ${pkg.version}` ); // 控制台输出 running version 1.0.0

const log = debug('app:log');
// 若是不是正式环境的话,不输出日志信息
if (ENV !== 'production') {
  // Enable the logger.
  debug.enable('*');
  log('Logging is enabled!');
  // Enable LiveReload
  document.write(
    '<script src="http://' + (location.host || 'localhost').split(':')[0] +
    ':35729/livereload.js?snipver=1"></' + 'script>'
  );
} else {
  debug.disable();
}

const res1 = a('kongzhi222');
const res2 = addArray([1, 2, 3, 4]);
console.log(11222211)
// Print the results on the page.
const printTarget = document.getElementsByClassName('debug__output')[0];

printTarget.innerText = `sayHelloTo('Jason') => ${res1}\n\n`;
printTarget.innerText += `addArray([1, 2, 3, 4]) => ${res2}`;

2. 安装PostCss插件
首先须要安装Rollup版本的PostCss插件,使用命令以下安装:
npm install --save-dev rollup-plugin-postcss
而后 添加插件到 rollup.config.js中去:
添加代码以下:

// Rollup plugins
import babel from 'rollup-plugin-babel';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import json from 'rollup-plugin-json';
import replace from 'rollup-plugin-replace';
import uglify from 'rollup-plugin-uglify';
import serve from 'rollup-plugin-serve';
import livereload from 'rollup-plugin-livereload';

// 新增的postcss
import postcss from 'rollup-plugin-postcss';

export default {
  input: './src/main.js',
  output: {
    file: './dist/js/main.min.js',
    format: 'iife'
  },
  plugins: [
    // 新增的postcss
    postcss({
      extensions: ['.css']
    }),
    resolve({
      jsnext: true,  // 该属性是指定将Node包转换为ES2015模块
      // main 和 browser 属性将使插件决定将那些文件应用到bundle中
      main: true,  // Default: true 
      browser: true // Default: false
    }),
    commonjs(),
    json(),
    babel({
      exclude: 'node_modules/**'  // 排除node_modules 下的文件
    }),
    replace({
      ENV: JSON.stringify(process.env.NODE_ENV || 'development')
    }),
    (process.env.NODE_ENV === 'production' && uglify()),
    serve({
      open: true, // 是否打开浏览器
      contentBase: './', // 入口html的文件位置
      historyApiFallback: true, // Set to true to return index.html instead of 404
      host: 'localhost',
      port: 10002
    }),
    livereload()
  ]
}

运行npm run build 后,能够看到生成的 dist/js/main.min.js 中的代码,在文件开头几行,能够看到一个名叫__$styleInject()的新函数;
代码以下:

function __$styleInject(css, returnValue) {
  if (typeof document === 'undefined') {
    return returnValue;
  }
  css = css || '';
  var head = document.head || document.getElementsByTagName('head')[0];
  var style = document.createElement('style');
  style.type = 'text/css';
  head.appendChild(style);
  
  if (style.styleSheet){
    style.styleSheet.cssText = css;
  } else {
    style.appendChild(document.createTextNode(css));
  }
  return returnValue;
}

这个函数建立了一个<style>元素并设置样式,而后添加到文档的<head>标签中。
但如今这些样式并无真正地被处理;PostCSS只是直接地传输了咱们的样式。让咱们添加一些须要的PostCSS插件,使得样式能在目标浏览器上工做。

3. 安装必要的 PostCSS插件
下面须要安装四个插件,以下插件:

postcss-simple-vars 可使用Sass风格的变量(e.g. $myColor: #fff;,color: $myColor;)而不是冗长的CSS语法(e.g. :root {--myColor: #fff},color: var(--myColor))。
postcss-nested 容许使用嵌套规则。实际上我不用它写嵌套规则;
postcss-cssnext 这个插件集使得大多数现代CSS语法(经过最新的CSS标准)可用,编译后甚至能够在不支持新特性的旧浏览器中工做。
cssnano — 压缩,减少输出CSS文件大小。至关于JavaScript中对应的UglifyJS。

使用以下命令安装便可:
npm install --save-dev postcss-simple-vars postcss-nested postcss-cssnext cssnano

咱们再来更下 rollup.config.js
如今咱们能够在rollup.config.js 中引入 postcss插件了,在配置对象的plugins属性上添加一个postcss。
以下代码:

// Rollup plugins
import babel from 'rollup-plugin-babel';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import json from 'rollup-plugin-json';
import replace from 'rollup-plugin-replace';
import uglify from 'rollup-plugin-uglify';
import serve from 'rollup-plugin-serve';
import livereload from 'rollup-plugin-livereload';
// 新增 rollup-plugin-postcss 插件
import postcss from 'rollup-plugin-postcss';

// 新增 postcss plugins
import simplevars from 'postcss-simple-vars';
import nested from 'postcss-nested';
import cssnext from 'postcss-cssnext';
import cssnano from 'cssnano';

export default {
  input: './src/main.js',
  output: {
    file: './dist/js/main.min.js',
    format: 'iife'
  },
  plugins: [
    // 新增的
    postcss({
      extensions: ['.css'],
      plugins: [
        simplevars(),
        nested(),
        cssnext({ warnForDuplicates: false, }),
        cssnano()
      ]
    }),
    resolve({
      jsnext: true,  // 该属性是指定将Node包转换为ES2015模块
      // main 和 browser 属性将使插件决定将那些文件应用到bundle中
      main: true,  // Default: true 
      browser: true // Default: false
    }),
    commonjs(),
    json(),
    babel({
      exclude: 'node_modules/**'  // 排除node_modules 下的文件
    }),
    replace({
      ENV: JSON.stringify(process.env.NODE_ENV || 'development')
    }),
    (process.env.NODE_ENV === 'production' && uglify()),
    serve({
      open: true, // 是否打开浏览器
      contentBase: './', // 入口html的文件位置
      historyApiFallback: true, // Set to true to return index.html instead of 404
      host: 'localhost',
      port: 10002
    }),
    livereload()
  ]
}

如今咱们再来运行 npm run build, 后再打开浏览器就能够看到了head里面新增样式了,而且已经压缩的。

注意:在cssnext()中配置了{ warnForDuplicates: false }是由于它和cssnano()都使用了Autoprefixer,会致使一个警告。 咱们只须要知道它被执行了两次(在这个例子中没什么坏处)而且取消了警告。

同理咱们运行命令 npm run watch 后,修改css,也能实时加载到最新的css了。

更多能够查看rollup中文文档

github项目rollup打包查看

相关文章
相关标签/搜索