Rollup 基础知识(2)

Design-Build.jpg

Rollup 官网

rollupjs.jpg

我们来看一看 vue 是使用了 Rollup 进行打包项目的。通过 npm 创建一个项目,然后创建 script.js 或者 index.js 文件,来作为可执行的脚步文件,首先我们需要引入所需要库。

今天我们就 vue 打包的源码分析来看一看 rollup 在 vue 中应用。


th (1).jpeg
const fs = require('fs')
const path = require('path')
const rollup = require('rollup')
const terser = require('terser')

fs 和 path 是 nodejs 提供有关文件操作和路径解析的包, rollup 和 terser 是用于构建打包项目库,当然这里 rollup 使我们今天主角。如果不存在 dist 文件夹我们就创建一个。

if (!fs.existsSync('dist')) {
    fs.mkdirSync('dist')
}

接下来读取 config 这个配置文件,

let builds = require('./config').getAllBuilds()
if (process.env.TARGET) {
  module.exports = genConfig(process.env.TARGET)
} else {
  exports.getBuild = genConfig
  //通常我们会调用这个
  exports.getAllBuilds = () => Object.keys(builds).map(genConfig)
}

这里输出 getAllBuilds 是返回一个方法,方法Object.keys 获取对象的属性集合,

var foo = {name:'koo',age:23}
undefined
Object.keys(foo)
(2) ["name", "age"]
Object.keys(foo).map(function(item){ console.log(foo[item])})
VM493:1 koo
VM493:1 23

用 genConfig 为每个要打包module输出配置

function genConfig (name) {
  const opts = builds[name]
  const config = {
    input: opts.entry,
    external: opts.external,
    plugins: [
      flow(),
      alias(Object.assign({}, aliases, opts.alias))
    ].concat(opts.plugins || []),
    output: {
      file: opts.dest,
      format: opts.format,
      banner: opts.banner,
      name: opts.moduleName || 'Vue'
    },
    onwarn: (msg, warn) => {
      if (!/Circular/.test(msg)) {
        warn(msg)
      }
    }
  }

  // built-in vars
  // const vars = {
  //   __WEEX__: !!opts.weex,
  //   __WEEX_VERSION__: weexVersion,
  //   __VERSION__: version
  // }
  // feature flags
  // Object.keys(featureFlags).forEach(key => {
  //   vars[`process.env.${key}`] = featureFlags[key]
  // })
  // build-specific env
  // if (opts.env) {
  //   vars['process.env.NODE_ENV'] = JSON.stringify(opts.env)
  // }
  // config.plugins.push(replace(vars))

  if (opts.transpile !== false) {
    config.plugins.push(buble())
  }

  Object.defineProperty(config, '_name', {
    enumerable: false,
    value: name
  })

  return config
}

这里主要是返回一个 rollup 在构建项目所用的配置文件,简单地解释一下 config 各个属性,

  • input 输入文件

  • plugins 插件,vue 开始使用 flow 来作为自己类型系统的,alias 方法
    -i, --input 要打包的文件(必须)
    -o, --output.file 输出的文件 (如果没有这个参数,则直接输出到控制台)
    -f, --output.format [es] 输出的文件类型 (amd, cjs, es, iife, umd)
    -e, --external 将模块ID的逗号分隔列表排除
    -g, --globals 以module ID:Global 键值对的形式,用逗号分隔开
    任何定义在这里模块ID定义添加到外部依赖
    -n, --name 生成UMD模块的名字
    -m, --sourcemap 生成 sourcemap (-m inline for inline map)
    --amd.id AMD模块的ID,默认是个匿名函数
    --amd.define 使用Function来代替define
    --no-strict 在生成的包中省略"use strict";
    --no-conflict 对于UMD模块来说,给全局变量生成一个无冲突的方法
    --intro 在打包好的文件的块的内部(wrapper内部)的最顶部插入一段内容
    --outro 在打包好的文件的块的内部(wrapper内部)的最底部插入一段内容
    --banner 在打包好的文件的块的外部(wrapper外部)的最顶部插入一段内容
    --footer 在打包好的文件的块的外部(wrapper外部)的最底部插入一段内容
    --interop 包含公共的模块(这个选项是默认添加的

  • Object.defineProperty 将 name 作为 _name 属性写入到 config 对象中并且为不可遍历。

根据 name 获取 opts, 就是 web-runtime-cjs-dev属性值,opts 对象提供压缩web-runtime-cjs-dev基本信息。我们可以将每个属性和上面函数进行对应。

const builds = {
  // Runtime only (CommonJS). Used by bundlers e.g. Webpack & Browserify
  'web-runtime-cjs-dev': {
    entry: resolve('web/entry-runtime.js'),
    dest: resolve('dist/zi.runtime.common.dev.js'),
    format: 'cjs',
    env: 'development',
    banner
  }
}
const aliases = require('./alias')
const resolve = p => {
  const base = p.split('/')[0]
  if (aliases[base]) {
    return path.resolve(aliases[base], p.slice(base.length + 1))
  } else {
    return path.resolve(__dirname, '../', p)
  }
}

alias 文件

const path = require('path')

const resolve = p => path.resolve(__dirname, '../', p)

module.exports = {
  web: resolve('src/platforms/web'),
}

build 函数接受 builds 作为参数通过回调中再次调用自己来完成异步执行完所有的构建任务。

build(builds)


function build(builds) {
    let built = 0
    const total = builds.length
    const next = () => {
        buildEntry(builds[built]).then(() => {
            built++
            if (built < total) {
                next()
            }
        }).catch(logError)
    }

    next()
}

最后看看 buildEntry 方法,我们这里调用 rollup 成功后构建项目代码通过 primise 来获取,然后就可以对处理好的代码进行一些写入附加信息等操作。

function buildEntry(config) {
    const output = config.output
    const { file, banner } = output
    const isProd = /(min|prod)\.js$/.test(file)
    return rollup.rollup(config)
        .then(bundle => bundle.generate(output))
        .then(({ output: [{ code }] }) => {
            if (isProd) {
                const minified = (banner ? banner + '\n' : '') + terser.minify(code, {
                    toplevel: true,
                    output: {
                        ascii_only: true
                    },
                    compress: {
                        pure_funcs: ['makeMap']
                    }
                }).code
                return write(file, minified, true)
            } else {
                return write(file, code)
            }
        })
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • 你是否是 JavaScript 新手?并且对模块,模块加载器和模块打包器感到困惑吗?或者你已经编写了一段时间的 J...
    钢钢_94d5阅读 1,823评论 0 2
  • 前言 前一段时间利用空闲时间学习了一下vue组件的封装,也在工作中进行了实践,将公司常用的一个api抽象成了vue...
    朱小维阅读 13,798评论 1 30
  • 1.几种基本数据类型?复杂数据类型?值类型和引用数据类型?堆栈数据结构? 基本数据类型:Undefined、Nul...
    极乐君阅读 5,496评论 0 106
  • rollup是一款小巧的javascript模块打包工具,更适合于库应用的构建工具;可以将小块代码编译成大块复杂的...
    IOneStar阅读 15,051评论 2 7
  • 33、JS中的本地存储 把一些信息存储在当前浏览器指定域下的某一个地方(存储到物理硬盘中)1、不能跨浏览器传输:在...
    萌妹撒阅读 2,067评论 0 2