基于rollup打包组件实战

前言

最近做项目,发现有很多可抽离出来的组件,以前开发组件是用gulp和webpack搭建的脚手架,需要配置一堆loader之类的东西,配置完成后,编译出来的代码不仅可读性差,而且代码体积偏大。因此想找寻新的编译工具,最后发现vue.jsreact.js等流行库都用了rollup.js来编译代码,而且rollup.js可以编译输出各种模块规范的代码AMD、Commonjs、UMD、IIFE。所以也入门rollup.js

rollup介绍

官方描述

Rollup 是一个 JavaScript 模块打包器,可以将小块代码编译成大块复杂的代码,例如 library 或应用程序。Rollup 对代码模块使用新的标准化格式,这些标准都包含在 JavaScript 的 ES6 版本中,而不是以前的特殊解决方案,如 CommonJS 和 AMD。ES6 模块可以使你自由、无缝地使用你最喜爱的 library 中那些最有用独立函数,而你的项目不必携带其他未使用的代码。ES6 模块最终还是要由浏览器原生实现,但当前 Rollup 可以使你提前体验。rollupjs官网

1、配置文件

1、安装对应的包


// rollup编译的核心模块
npm install rollup -D   

// rollup的ES6编译插件
npm install rollup-plugin-babel -D

// 一堆编译的loader
npm install -D @babel/cli @babel/core @babel/node @babel/plugin-transform-react-jsx @babel/preset-env @babel/preset-react @babel/runtime @babel/plugin-external-helpers @babel/plugin-proposal-object-rest-spread @babel/plugin-syntax-object-rest-spread 

// plugin插件
npm install -D rollup-plugin-commonjs rollup-plugin-node-resolve rollup-plugin-serve rollup-plugin-uglify rollup-plugin-livereload rollup-plugin-postcss

2、文件目录


.
├── build // 编译打包后的文件夹
│   ├── css
│   │   └── index.css // css
│   ├── img  // 图片无法自动打包过去
│   │   ├── plusRightsTab.png
│   │   └── qiy-icon_1.png
│   └── js
│       └── index.js
├── config
│   ├── build.js
│   ├── compile_task.js      // 编译文件
│   ├── dev.js
│   ├── rollup.config.dev.js     // 开发环境配置文件
│   ├── rollup.config.js     // 公用配置文件
│   └── rollup.config.prod.js       // 生产环境配置文件
├── index.html          入口html
├── package-lock.json
├── package.json
├── postcss.config.js        // 移动端将px转换为rem的配置文件
└── src
    ├── img
    │   ├── plusRightsTab.png
    │   └── qiy-icon_1.png
    ├── js
    │   └── index.js
    └── sass
        ├── _init.scss
        ├── _mixin.scss
        └── tabs.scss
    

2、rollup配置

1、编译配置文件rollup.config.js

/**
 * Created by wangjia16 on 2019/8/12.
 */
const ENV = process.env.NODE_ENV;
const path = require('path');
const babel = require('rollup-plugin-babel');
const buble = require('rollup-plugin-buble');
const json = require('rollup-plugin-json');

// 编译npm模块及其全局变量模块 插件模块
const nodeResolve = require('rollup-plugin-node-resolve');
const commonjs = require('rollup-plugin-commonjs');
const nodeGlobals = require('rollup-plugin-node-globals');
//开启服务插件
const serve = require('rollup-plugin-serve');
//编译css
const postcss = require('rollup-plugin-postcss');
const sass = require('node-sass');
// 处理rem换算
// const pxtorem = require('postcss-pxtorem');
const px2rem = require('postcss-px2rem');

const image = require('rollup-plugin-img');
// 监听文件改变,并刷新浏览器
const livereload = require('rollup-plugin-livereload');

const resolveFile = function (filePath) {
    return path.join(__dirname, '..', filePath)
};

const resoleFileName = function (filePath) {
    let imgPath = '../build';
    return path.join(__dirname, imgPath, filePath)
};

const isProductionEnv = ENV === 'production';

const processSass = function(context, payload) {
    return new Promise(( resolve, reject ) => {
        sass.render({
            file: context
        }, function(err, result) {
            console.log(result);
            if( !err ) {
                resolve(result);
            } else {
                console.log(err);
                reject(err)
            }
        });
    })
};


module.exports = [
    {
        input: resolveFile('src/js/index.js'),
        output: {
            file: resolveFile(`build/js/index.js`),
            // format: 'cjs',
            format: 'umd',
            name: 'panTabs',
        },
        plugins: [
            postcss({
                extract: './build/css/index.css',
                // extract: true,
                minimize: isProductionEnv,
                extensions:['css','scss'],
                process:processSass,

            }),
            json(),
            babel({
                exclude: '**/node_modules/**'
            }),
            buble(),
            nodeResolve({
                // module: true, // ES6模块尽可能使用 ‘module’字段
            }),
            commonjs({
                include: [
                    'node_modules/**'
                ],
                exclude: [
                    'node_modules/process-es6/**'
                ],
                namedExports: {
                    'node_modules/react/index.js': ['Component', 'PureComponent', 'Fragment', 'Children', 'createElement']
                }
            }),
            nodeGlobals(),
            // 开启服务
            ENV == 'development' ?
            serve({
                open: true, // 是否打开浏览器
                contentBase: './', // 入口html的文件位置
                historyApiFallback: true, // Set to true to return index.html instead of 404
                host: 'localhost',
                port: 3003
            })
            : '',
            livereload()
        ],
    },
];

注意:如果是umd,需要注意的是umd格式必须指定模块的名称,通过name属性来实现

基于rollup打包组件实战_第1张图片

2、编译rollup.config.dev.js文件

process.env.NODE_ENV = 'development';
const configList = require('./rollup.config');

configList.map((config, index) => {
    config.output.sourcemap = true;
    return config;
});


module.exports = configList;

3、编译rollup.config.prod.js文件

process.env.NODE_ENV = 'production';
const { uglify } = require('rollup-plugin-uglify');
const configList = require('./rollup.config');

configList.map((config, index) => {
    config.output.sourcemap = false;
    config.plugins = [
        ...config.plugins,
        ...[
            uglify()
        ]
    ];
    return config;
});

module.exports = configList;

4、.babelrc文件配置

{
  "presets": [
    "@babel/preset-react",
    [
      "@babel/preset-env",
      {
        "modules": false
      }
    ]
  ],
  "plugins": [
    "@babel/plugin-proposal-object-rest-spread",
    "@babel/plugin-syntax-object-rest-spread",
    "@babel/plugin-transform-react-jsx",
    [
      "@babel/plugin-transform-runtime",
      {
        "absoluteRuntime": false,
        "corejs": false,
        "helpers": false,
        "regenerator": false,
        "useESModules": false
      }
    ]
  ]
}

5、在package.json里配置执行脚本


"dev": "node ./config/dev.js",
 "build": "node ./config/build.js"

执行脚本,编译

1、执行脚本后,会自动启动浏览器

  • 在项目中执行npm run dev,编译结果在目录build/index.js
  • 编译结果为
    基于rollup打包组件实战_第2张图片

常见错误

1、编译react时,plugins位置放置不对,会导致语法错误

 plugins: [
	 // 原先的位置,放在这里会导致语法错误
	 // nodeResolve(),
     // commonjs(),
     // nodeGlobals(),
     postcss({
        extract: true,
        minimize: isProductionEnv,
        extensions:['css','scss'],
        process:processSass        
      }),
      json(),
      babel({
          exclude: '**/node_modules/**'
      }),
       buble(),
       nodeResolve(),
       commonjs(),
       nodeGlobals(),       
]

基于rollup打包组件实战_第3张图片
2、编译react,还会出现的错误
基于rollup打包组件实战_第4张图片

意思是说 React目前没有真正提供ES模块,所以需要在配置中解决这一问题
解决方案是在插件commonjs里进行配置

配置如下

commonjs({
    include: [
         'node_modules/**'
     ],
         exclude: [
             'node_modules/process-es6/**'
         ],
         namedExports: {
            'node_modules/react/index.js': ['Component', 'PureComponent', 'Fragment', 'Children', 'createElement']
        }              
}),

总结

本文简单介绍了rollupjs针对js,sass所做的编译处理,记录在此,一是分享给需要的同学使用,二是方便自己后续回看。

使用场景
  • 想要快速配置开发组件
  • 要用ES6+语法开发
  • 代码清洁,清理无用代码(tree-shaking)

参考资料:

  • rollup官网:rolluojs.com
  • rollupjs实战学习笔记

你可能感兴趣的:(工程化,前端,rollup,工具化,组件)