篇九:大前端之模块打包工具webpack与rollup笔记

2,080 阅读18分钟

文章输出主要来源:拉勾大前端高新训练营(链接) 与 webpack官网、rollup官网。小哥哥小姐姐请不要嫌弃啰嗦,下面肯定都是干货。

Webpack

1. 基本使用

1.1 简单尝试

  1. 创建并初始化项目

    mkdir wepack-demo
    cd wepack-demo
    yarn init -y
    
  2. 安装webpack

    yarn add webpack webpack-cli -D
    
  3. 创建src目录并编写以下简单测试代码

    // src/hello.js
    const hello = function() {
      const h1 = document.createElement('h1');
      h1.innerText = 'Hello world';
      return h1;
    }
    
    export default hello;
    
    // src/index.js
    import hello from './hello';
    
    const element = hello();
    document.body.appendChild(element);
    
  4. 运行yarn webpacknpx webpack进行打包,生成dist/main.js文件,创建index.html文件引用并在浏览器打开即可查看效果

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Document</title>
    </head>
    <body>
      <script src="./dist/main.js"></script>
    </body>
    </html>
    

通过package.json中的"script"中可指定"build": "webpack",将其加入npm scritp,方便使用

1.2 使用配置文件

以上方式为webpack最简单的尝试,更常用的方式是通过配置文件的方式进行使用。

默认配置文件名称为webpack.config.js,是在node环境中运行的代码,通过module.exports = {}导出相关配置项。

// webpack.config.js
const path = require('path');
module.exports = {
  entry: "./src/index.js", // 打包入口文件
  output: { // 输出配置
    filename: 'main.js', // 输出的文件名
    path: path.resolve(__dirname, 'dist'), // 输出的目录,必须为绝对路径。
  }
}

以上为webpack最简单的配置,值得注意的是输出的path必须是绝对路径,否则报错,可以借助path模块的resolve方法进行设置。

2. webpack的配置选项

在使用webpack时,我们需要做的大多数的工作就是给webpack的配置文件添加不同的配置选项,进而达到自己的目标,以下为webpack中一些常用的配置选项。

2.1 工作模式mode

webpack可以针对不同的环境进行打包,默认不同的环境配置也是不同的,webpack提供了三种mode: 参考官方mode配置

  • development
  • producttion
  • none: 当选项为none时候,不会启用任何默认插件,此时方便我们查看打包后的代码,对打包基本原理进行了解

配置方式:

  • 通过参数方式webpack --mode none

  • 通过配置文件

    module.exports = {
      ...
      mode: 'none'
      ...
    }
    

2.2 通过loader处理不同类型的资源

webpack本身只能打包js代码,无法打包其他类型的资源,如需打包其他类型的资源,需要借助相关的loader进行实现。

loader是webpack提供的一种机制,每个loader的具体使用方式可以查阅官方文档。一下介绍几个常用的loader

2.2.1 打包CSS资源

  1. 安装css-loader: yarn add css-loader -D

  2. 配置文件中进行配置

    module.exports = {
      ...
      module: { // 添加module字段
        rules: [ // 在rules数组中配置具体的loader
          {
            test: /\.css$/, // 通过test指定具体的后缀名,处理该资源
            use: 'css-loader' // 在use中添加loader名称即可进行最简单的loader使用
          }
        ]
      }
      ...
    }
    
  3. yarn build(在package.json中的script中已经配置了build对应webpack命令)进行打包,此时页面中无法展示样式,通过查看的打包main.js文件可以发现, css-loader只是将css文件转换为了字符串,并没有使用该模块,此时可借助style-loader将其插入html中.

  4. yarn add style-loader -D安装syle-loader并配置,此时重新打包即可看到css生效

    module.exports = {
      ...
      module: {
        rules: [
          {
            test: /\.css$/,
            use: ['style-loader', 'css-loader'] // 将use变为数组形式,添加style-loader, loader的使用顺序是从后向前进行的,需要先使用css-loader处理css文件转换为字符串,在通过style-loader创建style标签将其插入html中
          }
        ]
      }
      ...
    }
    

2.2.2 打包文件资源

在webpack中打包类似图片等资源可以使用file-loader

// js文件中引入图片,此时可以用file-loader进行处理,否则打包会报错
import imgSrc from './assets/yaoyao.gif';
function addImg() {
  const img = document.createElement('img');
  img.src = imgSrc;
  document.body.appendChild(img);
}
addImg() // 页面添加一个展示图片的元素
  1. 安装:yarn add file-laoder -D

  2. 配置文件中使用:

    module.exports = {
      ...
      module: {
        rules: [
          {
            test: /\.css$/,
            use: ['style-loader', 'css-loader']
          },
          {
            test: /\.(png|svg|jpg|gif)$/, // 指定打包资源的后缀名
            use: ['file-loader']  // 使用file-loader
          }
        ]
      }
    }
    
  3. 重新打包并预览,此时如果页面中图片加载失败,需要查看一下img标签的src设置的是否是正常的,一般是少了一些前缀,例如图片在dist/xxx.png,而代码里直接是xxx.png,此时可以设置publicPath指定引入资源的前缀

    module.exports = {
      ...
      output: {
        filename: 'main.js',
        path: path.resolve(__dirname, 'dist'),
        publicPath: './dist/'
      },
      ...
    }
    

    注意:

    使用publicPath时候它会被当前做字符串拼接在资源路径前面,因此./dist/最后的斜线不能省略,打包后的代码如下:

    // __webpack_public_path__
    __webpack_require__.p = "./dist/";
    ...
    /* harmony default export */
    __webpack_exports__["default"] = (__webpack_require__.p + "1bbd3769c5117cd56d6b8ebc5ac3576a.gif"); // 直接暴力相加,因此设置publicPath要精确
    

通过查看打包后的代码,可以看出file-loader所做的事情就是复制了图片资源到dist,并导出了图片资源的路径。

2.2.3 url-loader处理文件资源

除了file-loader可以处理其他静态资源,url-loader也可以处理,不同的是,url-loader可以将资源通过data urls(点击可查看Data URLs具体语法)方式进行加载。

Data URLs组成: 前缀(data:)、指示数据类型的MIME类型、如果非文本则为可选的base64标记、数据本身

data:[<mediatype>][;base64],<data>

一般非文本资源会被转换为base64,在通过Data URLs的方式进行加载,而不会在dist中创建新的文件。

对于项目中的小文件可以将其转为base64,减少http请求次数,由于base64编码过后文件大小会变为原来的4/3,所以为了减小项目体积,大文件不适合转为base64。url-loader也可以通过配置选项实现这种方式:

module: {
    rules: [
      ...
      {
        test: /\.(png|svg|jpg|gif)$/,
        use: { // use通过对象形式可以对loader设置配置选项
          loader: 'url-loader',
          options: {
            limit: 10 * 1024 // 这里limit设置10 * 1024代表10kb以下的图片才会被转为base64的方式,超过10kb的还按照file-loader进行处理.
          }
        }
      }
    ]
  }

注意:

在使用limit选项时,由于超过限制的文件需要使用file-loader进行处理,所以项目中还需安装file-loader,否则将会报错。

2.2.4 处理ES6代码的转换

webpack作为模块打包器,默认支持了import,export,但并不支持ES6的语法自动转换ES6代码,还需借助babel进行转换。

安装babel-loader与babel插件: yarn add babel-loader @babel/core @babel/preset-env -D

使用loader:

module.exports = {
  module: {
    rules: [
      {
        test: /\.js$/,
        use: [ // 如果是一个loader,可以向上面通过对象的方式配置,如果是多个loader,可以在一个数组中,通过对象的方式进行配置以及可选项设置。这里进行数组方式使用的演示。
          {
            loader: 'babel-loader',
            options: {
              presets: ["@babel/preset-env"]
            }
          }
        ]
      }
    ]
  }
}

2.2.5 webpack对于模块化的处理

webpack兼容多种模块化方案:例如ES Module、CommonJS、AMD等

通过CommonJS导入ES Module中的默认导出需要使用default属性:

const defaultContent = require('./esmodule.js').default;

对于css中的@importurl以及html中的src等涉及到加载模块的指令或属性也可以触发webpack的模块加载。

html中的href属性也可以通过配置html-loader的配置选项,触发模块的打包

安装:yarn add html-loader -D

配置:

{
  test: /\.html/,
  use: {
    loader: 'html-loader',
    options: {
      attrs: ['img:src', 'a:href']
    }
  }
}

2.2.6 loader的工作原理

loader就是拦截对应后缀名的文件,将其内容交给一段程序进行处理,以下为一个简单的markdown-loader的实现

// markdown-loader.js
const marked = require('marked'); // yarn add marked -D安装marked解析器,将markdown解析为html字符串

module.exports = (source) => { // 导出一个函数,里面是loader具体做的事情,参数为markdown内容
  return `export default ${JSON.stringify(marked(source))}`; // 返回的代码需要是javascript代码,不然会报错。
}

使用:

{
  test: /\.md$/,
  use: ['./markdown-loader']
}

或者可以借助html-loader去处理html字符串

// markdown-loader.js
const marked = require('marked');

module.exports = (source, map, meta) => {
  console.log(source);
  const html = marked(source);
  return html; // 如果返回html字符串,则需要额外使用html-loader进行处理
}

使用:

{
  test: /\.md$/,
  use: ['html-loader', './markdown-loader'] // 先通过markdown-loader将markdown处理为html字符串,再通过html-loader进行处理
}

2.2.7 小结

webpack本身只能打包js代码,借助loader可以实现对不同资源打包,loader的类型主要可以分为三种:

  • 编译转换类:例如babel-loader, css-loader等
  • 文件操作类:例如file-loader,url-loader等
  • 代码检查类:例如eslint-loader等

2.3 webpack中的插件(Plugin)

webpack中除了loader,还有插件,两者主要区别为:

  • Loader: 实现不同资源模块的加载
  • Plugin: 除了加载资源在外的其他自动化操作,例如:
    • 打包前自动清除
    • 拷贝静态资源
    • 压缩代码等

每个插件都是独立存在的,更深入的使用方式可以查阅自己需要的插件的官方文档

2.3.1 自动清除dist目录插件

通过clean-webpack-plugin可以在每次打包之前自动帮我们删除dist目录

  1. 安装: yarn add clean-webpack-plugin -D

  2. 配置文件中使用:

    const { CleanWebpackPlugin } = require('clean-webpack-plugin');
    module.exports = {
    	...
    	plugins: [
        new CleanWebpackPlugin()
      ]
    }
    
  3. 重新打包生效

2.3.2 自动生成HTML文件的插件html-webpack-plugin

html-webpack-plugin可以自动生成html文件并将依赖的bundle添加到html中,避免开发者手动修改。

  1. 安装:yarn add html-webpack-plugin -D

  2. 配置文件中导入使用:

    const HtmlWebpackPlugin = require('html-webpack-plugin');
    module.exports = {
    	...
    	plugins: [
        new HtmlWebpackPlugin()
      ]
    }
    
  3. 重新打包,生成代码中就会存在index.html,并引入了依赖的js文件

添加配置项

html-webpack-plugin所有配置与深入使用可以点击查看官方文档。以下为常用配置:

module.exports = {
	...
	plugins: [
    new HtmlWebpackPlugin({
      title: 'Webpack Plugins learning',
      meta: {
        viewport: 'width=device-width'
      }
    })
  ]
}

打包生成html:

<title>Webpack Plugins learning</title>
<meta name="viewport" content="width=device-width">

使用模板:

简单的使用可以通过配置项进行设置,如需自定义更多内容则需使用自定义模板的方式。

在html模板中可以通过lodash模板语法的方式,即<%= variable %>语法,由htmlWebpackPlugin.options注入在htmlWebpackPlugin中定义的选项内容

module.exports = {
	...
	plugins: [
    new HtmlWebpackPlugin({
      title: 'Webpack Plugins learning',
      meta: {
        viewport: 'width=device-width'
      },
      template: './index.html'
    })
  ]
}

在html中注入变量

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
  <div><%= htmlWebpackPlugin.options.title %></div>
</body>
</html>

注意:

如果使用了html-webpack-plugin的模板,且模板以.html结尾,且在loader中使用了html-loader处理.html的文件,打包时候可能会出现错误。此时可以通过给模板文件换个后缀进行处理,例如换成.ejs

如需创建多个页面,例如多也应用的项目,创建html-webpack-plugin实例即可:

module.exports = {
  ...
  plugins: [
    new HtmlWebpackPlugin({
      title: 'Webpack Plugins learning',
      meta: {
        viewport: 'width=device-width'
      },
      template: './index.html'
    }),
    new HtmlWebpackPlugin({
      filename: 'about.html'
    })
  ]
}

2.3.3 webpack插件原理与自定义插件

webpack通过在打包的不同环节添加不同的钩子函数,在特定时期可以针对文件做不同的操作,插件的原理就是通过在这些不同的时期添加一些特定的钩子函数,达到自己的目标。官方自定义插件文档

webpack插件的构成:

  • 必须是个具名的JavaScript函数或JavaScript类
  • 在其prototype上必须定义apply方法
  • 必须指定要接入的事件钩子,通过事件的tap方法接入事件
  • 需要操作webpack内部实例的特定数据
  • 在操作完成后必须调用webpack提供的回调

以下为一个删除打包文件中注释的自定义插件

class RemoveComments {
  apply(compiler) { //compiler api文档 https://webpack.docschina.org/api/compiler-hooks/
    compiler.hooks.emit.tap('RemoveComments', compilation => { // compilation api 文档 https://webpack.docschina.org/api/compilation-hooks/
      // 通过compilation实例能够访问所有的模块和它们的依赖,可以理解为此次打包的上下文
      for(const name in compilation.assets) {
        if (name.endsWith('.js')) {
          const content = compilation.assets[name].source()
          const withoutComments = content.replace(/\/\*\*+\*\//g, '')
          compilation.assets[name] = {
            source: () => withoutComments,
            size: () => withoutComments.length
          }
        }
      }

    })
  }
}

2.3 webpack-dev-server

在开发阶段,为了提高开发效率,可以通过webpack-dev-serve帮助我们启动一个http服务器,通过http方式查看网页的效果,并且可以监听代码的修改实时刷新浏览器等。深入内容可以点击链接查看官网教程。以下为简单使用:

  1. 安装: yarn add webpack-dev-server -D

  2. 通过配置文件使用:

    module.exports = {
      ...
      devServer: {
        contentBase: path.join(__dirname, "public"), // contentBase用于指定访问静态资源的路径,在开发阶段为了提高效率通常不会将静态资源复制到dist中,只有生产环境中才会复制,因此在开发阶段可以通过这个属性设置访问静态资源的路径
        proxy: { // proxy可以将接口请求代理到后端真实的api地址,开发阶段通过代理的方式可以避免遇到跨域问题,原因是跨域是浏览器级别的限制,服务端不存在跨域限制,通过node将同源的请求代理到真实地址,再将结果返回给浏览器
          "/api": {
            target: "https://other-server.example.com",
            secure: false
          }
        }
      },
      ...
    }
    
  3. 通过yarn webpack-dev-server启动http服务。

具体的配置项通过官方文档www.webpackjs.com/configurati…

Webpack-dev-server启动后会将打包结果放到内存中,避免反复的磁盘读写,从而提高构建效率。

2.4 source map

通过source map可以方便地进行调试,在调试时如果遇到报错,通过sorce map可以更准确的定位到错误的地方。

webpack中通过devtool属性进行source map的配置,文档:webpack.docschina.org/configurati…

// 用法:
module.exports = {
  devtool: 'cheap-module-source-map'
}

一下介绍几种常用配置的信息:

  • evel模式: evel('console.log(123) // # sourceURL=./foo/bar.js')函数可以将evel中传入的字符串当做js代码执行,后面的sourceURL注释可以指定源代码文件路径,以此可以实现source map机制。evel模式会将源码定位到打包后的代码位置,并非开发时写代码的位置。
  • eval-source-map模式:不仅可以定位到出错代码文件,还可以定位到出错的行列信息,
  • eval-cheap-source-map模式:从外形看多了cheap选项,可以定位到出错代码文件与行信息,速度比evel-source-map
  • eval-cheap-module-source-map模式:带module的模式可以定位到我们手写的源代码,不带module的模式会定位到loader解析后的代码中

通过观察规律,evelcheapmodule等可以任意组合cheap-module-source-map就是没有使用evel的模式,其效果跟eval-cheap-module-source-map比较类似。

除此之外还有inline的方式,它会将生成的sourcemap直接打包进源码中,其他方式会生成单独的source-map文件。nosources只会提示错误的文件,但不会生成真正的源码内容。

source-map使用推荐:

  • 开发环境: eval-cheap-module-source-map,相对速度比较快,通过定位到行就可以很方便地确定错误
  • 生产环境:nonenosources-source-map,生产中使用source-map会暴露源码信息,且打包的的体积比较大,因此建议不使用source map或者使用不生成源码的source map仅仅告诉我们错误位置。

2.5 模块热替换(hot module replacement)

在默认情况下,更改代码会导致页面刷新,会导致页面中的操作状态丢失,通过HMR的机制可以仅更改修改的模块,而不需要重新加载整个页面。

使用方式:

devServer: {
  hot: true,
}

通过hot配置项可以开启HMR,类似CSS、vue组件等有规律的模块,在loader中默认就可以实现HMR。对于无规则自定义的js文件,则需要通过手动操作api的方式实现HMR的替换逻辑。

HMR官方文档及示例:webpack.docschina.org/guides/hot-…

简单介绍:

通过在代码中判断module.hot可以确定是否开启了HMR,通过module.hot.accept(modulePath, function() {//替换逻辑})方法可以自定义实现在模块代码更改后需要做的操作,在该模块的代码发生改变后,就不会触发浏览器刷新,而回忆触发定义的回调函数,以此实现模块热替换。

注意:

使用hot选项开启HMR之后,如果在编写HMR的回调函数中的代码出错,则不会再浏览器console中报错,而是会回退到使用刷新浏览器的方案。可以将hot换为hotOnly,则会在浏览器中进行报错,而不刷新页面。

在使用HMR api时,需要通过module.hot进行判断,否则如果没有开启HMR,则会遇到报错。

在打包后,HMR的代码会被被移除,不会影响生产环境。

2.6 生产优化

webpack默认在production模式打包时已经做了一些优化配置,例如压缩代码、tree shaking等。以下介绍一些webpack优化相关的内容

2.6.1 DefinePlugin注入全局成员

该插件为webpack自带的插件,文档:webpack.docschina.org/plugins/def…

使用方式: 通过传参对象添加key-value形式注入全局成员

const webpack = require('webpack');

module.exports = {
  plugins: [
    new webpack.DefinePlugin({
      SERVICE_URL: JSON.stringify('https://dev.example.com'), // 传入的字符串会被当做js代码,如果为字符串可以借助JSON.stringify的方法
      TWO: '1+1' 
    })
  ]
}

打包生成的代码

// 源代码
console.log(SERVICE_URL)
console.log(TWO)

// 打包生成的代码
console.log("https://dev.example.com");
console.log(1+1);

2.6.2 tree-shaking

tree-shaking意义在于删除未引用到的多余代码,从而减小打包后的代码体积。在production模式中会自动被开启。官方文档:webpack.docschina.org/guides/tree…

在其他模式中手动开启:

module.exports = {
  ...
  mode: 'development',
	optimization: { // 通过添加optimization可以添加优化策略,通一下两个配置项开启tree-shaking
	  usedExports: true, // 只导出用到的模块
    minimize: true // 压缩代码并删除未引用的代码
	},
};

concatenateModules配置项:

文档:webpack.docschina.org/configurati…,

默认打包会将每个模块打包到一个函数中,开启此配置后会将多个模块合并到同一个函数中

module.exports = {
  ...
  mode: 'development',
	optimization: {
	  usedExports: true,
    minimize: true,
    concatenateModules: true
	},
};

tree-shaking注意事项:

tree-shaking的实现必须借助ESM,如果代码被babel转换为了commonjs,则无法实现tree-shaking,需要将其配置为开启ESM。(最新@babel/preset-env默认开启ESM)

sideEffects

生产模式默认为true,文档:webpack.docschina.org/configurati…

通常配合tree-shaking,如果确定项目的代码中没有副作用,则应开启。否则将会造成副作用代码被误删除。

module.exports = {
  ...
  mode: 'development',
	optimization: {
	  usedExports: true,
    minimize: true,
    concatenateModules: true
    sideEffects: true, // 开启后可以在package.json中指定副作用
	},
};
// package.json
{
  "sideEffects": false, // 代码中没有副作用
}

{
  "sideEffects": ["*.css"], // 通过数组指定有副作用的代码文件,符合条件的将不会被误删除
}

2.6.3 code splitting代码分割

webpack中可以通过code splitting将不同功能的代码打包到不同的budle中,从而实现浏览器加载时按需加载,提高响应速度。

实现方式有两种:

  • 多入口文件打包,输出时配置为占位符名称,生成多个bundle,适用于多页应用,其中如果有多个页面依赖公共代码,可以将公共代码提取出来单独打包,可以通过splitChunks进行配置

    // 示例
    module.exports = {
      entry: {//多入口
        'index'             : ['./src/page/index/index.js'],
        'list'              : ['./src/page/list/index.js'],
        'detail'            : ['./src/page/detail/index.js'],
        'cart'              : ['./src/page/cart/index.js'],
      },
      output: {
        filename          : 'js/[name].js', // 输出文件名使用占位符
        path              : path.resolve(__dirname, 'dist'),
      },
      optimization: {
        splitChunks: { // 不同页面依赖的公共代码通过配置splitChunk进行提取,生成公共模块
          chunks: "all", 
          minSize: 0, // 模块的最小体积
          minChunks: 2, // 模块的最小被引用次数
          name: 'base',
          cacheGroups: { // 缓存组
            vendors: {
              test: /[\\/]node_modules[\\/]/,
              priority: -10
            },
            default: {
              minChunks: 2,
              priority: -20,
              reuseExistingChunk: true
            }
          }
        }
      },
      plugins: [ // 通过HtmlWebpackPlugin可以为不同的模板指定不同的入口,将各自打包后的结果进行引入
        new HtmlWebpackPlugin(getHtmlConfig('index', 'SchoolMall首页')),
        new HtmlWebpackPlugin(getHtmlConfig('list', '商品列表')),
        new HtmlWebpackPlugin(getHtmlConfig('detail', '商品详情')),
        new HtmlWebpackPlugin(getHtmlConfig('cart', '购物车')),
      ]
    }
    
  • 通过ES Moudle的import动态导入,webpack将会自动进行分包。通过webpack魔法注释可以给import动态导入的文件分包时进行命名。使用方式如下

    import(/* webpackChunkName: 'detail' */ './src/detail')
    

webpack提供的魔法注释有多种,每种魔法注释都有自己的作用,详情查看文档:webpack.docschina.org/api/module-…

2.6.4 其他优化

MiniCssExtractPlugin可以将CSS提取到单独的css文件中,通过link方式引用

OptimizeCssAssetsWebpackPlugin可以对CSS文件进行代码压缩

2.6.5 小结

通常webpack中代码的优化方案思路可以从代码压缩、code split、http请求数量(分包、小文件走base64)、缓存等方面进行考虑

Rollup.js

Rollup 是一个 JavaScript 模块打包器,通常用于打包各种类库,webpack常用语对项目进行打包。官网文档:www.rollupjs.com/guide/intro…

1. 基本使用

安装yarn add rollup -D

通过命令行参数使用yarn rollup ./src/index.js --file dist/bundle.js --format iife

  • --file指定输出的文件

  • --format指定打包输出的格式,IIFE为立即执行函数的方式

    // IIFE打包结果
    (function () {
      'use strict';
    	// your code
    }());
    

    其他方式:cjs 适用于Node.js, umd适用于浏览器和Node.js,amd适用于浏览器

tree-shaking:rollup打包后会自动移除未使用的代码

2. 使用配置文件

创建rollup.config.js文件

export default { // rollup支持使用ESM编写配置文件,因此这里是export default
  input: 'src/index.js',
  output: {
    file: 'dist/bundle.js',
    format: 'umd'
  }
};

使用yarn rollup --config运行会默认使用rollup.config.js配置文件,也可以在--config之后指定配置文件``yarn rollup --config rollup.config.js`

3. rollup中的插件

rollup与webpack不同的是,它只有插件机制,所有的扩展都是通过插件完成的。

插件文档:www.rollupjs.com/guide/tutor…

json插件的使用:

安装: yarn add rollup-plugin-json -D

使用:

import json from 'rollup-plugin-json';

export default {
  input: 'src/index.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife'
  },
  plugins: [
    json()
  ]
};

npm模块的加载

官方文档:www.rollupjs.com/guide/tools…

rollup默认只能打包通过本地文件路径引入的模块,无法打包npm安装到node_modules中的模块,通过rollup-plugin-node-resolve插件可以解决此问题

安装:yarn add rollup-plugin-node-resolve -D

使用:

import json from 'rollup-plugin-json';
import resolve from 'rollup-plugin-node-resolve';

export default {
  input: 'src/index.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife'
  },
  plugins: [
    json(),
    resolve()
  ]
};

此时就可以正常打包在代码中使用npm模块模块了

例:

import _ from 'lodash-es';

console.log(_.camelCase('hello world'))

加载CommonJS

rollup默认只能使用ES Module,如果要兼容CommonJS,可以通过rollup-plugin-commonjs插件进行支持。官网:github.com/rollup/roll…

安装:yarn add rollup-plugin-commonjs -D

使用:

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

export default {
  input: 'src/index.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife'
  },
  plugins: [
    json(),
    resolve(),
    commonjs()
  ]
};

ESM中可以通过默认导入的方式导入commonjs中导出的内容

// 例:
//cjs.js
module.exports = {
  title: 'tom and jerry',
  roles: 'cat and mouse'
}

//index.js
import cjs from 'cjs';

4. code spliting

rollup可以通过ESM的import动态导入自动分包,此时format配置项不能为iife,iife会将所有代码打包到同一个函数中,无法实现分包。输出也需要配置为dir而不是指定为file

例:

配置:

export default {
  input: 'src/index.js',
  output: {
    dir: './dist',
    format: 'amd'
  }
};

分包代码:

import('./foo').then(res => {
  console.log(res);
})

5. 多入口打包

通过将input配置为一个数组或者跟webpack一样的对象的形式可以进行多入口打包,同样此时不能使用iife模式,可以选择amd,umd等方式

export default {
  input: ['src/index.js', 'src/foo.js'],
  output: {
    dir: './dist',
    format: 'amd'
  }
};