彻底学会rollup打包vue组件,逐步实现组件库打包

10,519 阅读6分钟

前置知识——rollup基础

rollup是什么

rollup是一款javascript模块打包器,它可以将小代码块编译成复杂的大块代码。当我们使用ES6模块编写应用或者库时,它可以打包成一个单独文件提供浏览器和Node.js来使用。

优点

  1. 将我们编写的多个文件组合成单个文件
  2. 静态分析代码,剔除未被使用到的代码块,保留有用代码块,减小打包文件的体积(tree-shaking)
  3. 在浏览器中支持使用 Node modules
  4. 基于ES2015模块,相比于webpack使用的CommonJs模块更加效率

warn:只在ES6模块中支持Tree-shaking,CommonJs不支持。 及应该使用import,而不应该使用require。

应用场景

和webpack相比,rollup更加的小巧简介,它更加适用于构建各种类库,比如你的项目需要代码拆分、含有图片、字体等资源。webpack比rollup更加适合。

基础使用

export default {

  input:'src/index.js',

  output:{

    file:'dist/index1.iife.js',

    format:'iife'

  }

}
  • input: rollup执行的入口文件
  • output: 文件输出配置
    • output.file: 输出文件路径名
    • output.format: rollup支持多种输出格式
      • iife: 输出用于浏览器的格式类型
      • cjs:用于NodeJs的格式类型
      • umd:既可用于浏览器,也可用于NodeJs
      • amd:用于像RequireJs模块加载的类型

如何处理并打包JS文件

  • 安装rollup

    打开终端 执行命令行 npm install --global rollup

  • 命令行打包

    新建main.js文件,添加代码如下:

const _keys = function(obj){
  if(Object.prototype.toString.call(obj) !== '[object Object]'){
      throw new Error('type is error')
  }
  const hasOwnProperty = Object.prototype.hasOwnProperty;
  let result = [];
  for(let prop in obj){
      if(hasOwnProperty.call(obj,prop)) result.push(prop)
  }
  return result;
}
export default _keys;

终端运行命令行,可以看到生成了bundle.js文件,--format后的参数可以替换成上述4种类型。

rollup main.js --file bundle.js --format iife

  • rollup.config.js 配置文件方式打包 每次使用命令行打包会很复杂,且很难自定义各种配置。rollup提供了一份配置文件来简化命令行操作并可启用rollup的复杂操作。

这个配置文件默认是rollup.config.js文件,通常我们在项目的根目录创建它。上面基础使用那段代码就是rollup.config.js文件最基本内容。除此,它还有其他配置项如:plugins、external、global等。

external: 在打包告诉rollup不要将external指定的外部依赖打包进来
global: 指定全局变量,类型为iife、umd时,window对象会将它指定作为属性
plugins: 插件组,引入的插件在此处执行

前置知识——Vue插件

插件通常用来为 Vue 添加全局功能,通过全局方法Vue.use(plugins)使用插件。它需要在实例化vue之前被调用。

Vue.use()会自动阻止多次注册相同的插件,即使多次调用也只会注册一次该插件。

通过源码,看Vue.use()

下图截取自vue源码 global-api下的use.js文件。它导出一个initUse方法,参数传入Vue。内部use方法接收plugins参数,该参数就是我们编写的插件。同时定义了一个数组,当数组中存在传入的插件,会直接返回。即实现自动阻止多次注册相同的插件。

const args = toArray(arguments,1)将传入的参数转换成数组,args.unshift(this)再将Vue对象添加到该数组的头部位置。

如果传入的plugin是一个对象且它包含一个install方法,那么就调用plugin对象的install方法,并将args参数传给它。

如果plugin自身就是一个方法,那么直接调用它,并传入args参数

图片.png

插件开发

通过上述源码分析,我们知道Vue.use()传入的插件必须是一个对象或一个函数,当为对象时,该对象必须包含一个install方法。通常,我们开发插件会以对象的形式。

//myplugin.js
const install = function(Vue){
    Vue.component('my-input',{
        template:'<p>自定义组件</p>'
    })
}
export default {
    install
}
//main.js
import Vue from 'vue'
import plugin from './plugins/myplugin.js'

Vue.use(plugin)

如此一个简单的插件就完成了,这是可以在App.vue中添加<my-input></my-input>就能在页面上展现出效果了。

实例:用rollup打包vue组件

  • 新建一个项目,项目内执行 npm init -y 进行初始化
  • 按如下项目结构创建相应的文件目录及文件

图片.png

在对应文件中填充相应代码如下:

// packages/button/index.js
import WnButton from './src/index.vue'
WnButton.install = function(Vue){
  Vue.component(WnButton.name,WnButton)
}
export default WnButton;
// packages/button/src/index.vue
<template>
  <button>
    <slot></slot>
  </button>
</template>
<script>
export default {
  name:"WnButton"
}
</script>
// src/index.js
import Button from '../packages/button/index.js'

const components = [
  Button
]

const install = function(Vue){
  components.forEach(component => {
    Vue.component(component.name,component)
  })
}
export default {
  install
}
//  rollup.config.js
export default {
  input:'src/index.js',
  output:{
    file:'lib/index.umd.js',
    format:'umd',
    name:'vue-plugins'
  }
}

解析编译vue文件

至此,简单代码填充结束,然后更改package.json文件,在“script”中添加"build":"rollup -c",最后在终端运行命令npm run build

你会发现,并没有按照我们所想的那样打包成功,他给我们抛出一个错误,告诉我们需要使用相应的插件来处理非Javascript代码。

图片.png 我们需要依赖 rollup-plugin-vuevue-template-compiler 来解析vue文件 (注:版本一定要匹配,本实例rollup-plugin-vue为5.x版本,之前下载6.0版本出了问题没研究)。 然后在rollup.config.js填充代码

import vuePlugin from 'rollup-plugin-vue'
export default{
    plugins:[vuePlugin()]
}

就是这么简单的几行,就可以处理vue文件啦

babel编译ES6语法

如果你的js代码中包含ES6语法,你需要将其转换成ES5,rollup给我们提供了babel插件,你只需要引用依赖,并在plugins中执行它。

所需相关的依赖包:@rollup/plugin-babel@babel/core@babel/preset-env

在根目录创建 .babelrc 文件,并填充

{
  "presets":["@babel/preset-env"]
}

rollup.config.js中填充代码

import babel from '@rollup/plugin-babel'
export default {
    plugins:[
        babel({
          babelHelpers:'bundled',
          exclude:'node_modules/**'
        })
    ]
}

解析css、less、sass

我们编写的组件肯定不会只有js语句和dom结构,css样式也是组件中重要的组成部分。我们可以在 .vue文件中直接以 style标签的形式写样式,这样是没有问题的。但这样是不友好的,我们希望能在 .css文件中维护组件的样式。

示例:我们在项目根目录新建文件夹assets,创建 style/index.css 文件,填充若干样式代码,然后在 src/index.js 中引入 import '../style/reset.less' 使用

执行打包命令,会抛出错误给我们,此时我们需要引入可以处理css的插件

postcssrollup-plugin-postcss

填充 rollup.config.js

import postcss from 'rollup-plugin-postcss'
export default {
    plugins:[
        postcss({
            extensions:['.css','.less'],
            extract:'index.css'
        })
    ]
}
  • extensions: 处理该数组内包含的扩展名,支持指定扩展名文件
  • extract: 如不使用该配置,样式会被打包进最终的包文件中,使用该配置,可将样式单独打包成指定文件

如使用extract,那么我们在使用main.js中使用插件,应使用如下方式

import plugins from './plugins/lib/index.umd.js'

import './plugins/lib/index.css'