最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

初识rollup 打包、配置vue脚手架

来源:博客园

rollup javascript 代码打包器,它使用了 es6 新标准代码模块格式。

特点:

  1. 面向未来,拥抱 es 新标准,支持标准化模块导入、导出等新语法。
  2. tree shaking 静态分析导入的代码。排除未实际引用的内容
  3. 兼容现有的 commonJS 模块,可通过插件导入

示例项目地址


(资料图片)

安装使用

创建示例项目

$> mkdir rollup-example$> cd rollup-example

安装 rollup

$> npm init -y$> npm i rollup

创建main.js主入口文件。创建 libs目录用于方式封装的功能函数。

package.json文件中定义执行脚本命令。

  • --file编译后的文件名称 简写 -o
  • --format按什么标准去编译文件类型 iffe、cjs、es。 简写-f
{  "scripts": {    "test": "echo \"Error: no test specified\" && exit 1",    "build": "rollup main.js --file bundle.js --format iife"  }}

libs创建arry.js

/** * 数组类型校验 * @param {*} target * @returns */export const isArray = (target) => {  return Array.isArray(target);};/** * 数组去重 * @param {*} target * @returns */export const duplicateKill = (target) => {  return [...new Set(target)];};

然后在main.js中调用

import { isArray } from "./libs/array";//console.log(isArray(3));console.log(isArray("1,2,3,4"));console.log(isArray([1, 2, 3, 4]));

执行npm run build,得到一个编译文件bundle.js

(function () {  "use strict";  /**   * 数组类型校验   * @param {*} target   * @returns   */  const isArray = (target) => {    return Array.isArray(target);  };  //  console.log(isArray(3));  console.log(isArray("1,2,3,4"));  console.log(isArray([1, 2, 3, 4]));})();

通过配置文件定义编译配置

上面使用了rollup命令,并通过命令行参数指定文件以及编译类型。

定义rollup.config.js文件,定义编译输出

// rollup.config.jsexport default {  input: "main.js",  output: {    file: "dist/bundle.js",    format: "iife",  },};

然后修改package.json

  • --config指定配置文件, 简写-c
  • --bundleConfigAsCjs因为配置文件是以 .js结尾的,通常建议使用.cjs.
{  "scripts": {    "test": "echo \"Error: no test specified\" && exit 1",    "build": "rollup --config rollup.config.js --bundleConfigAsCjs"  }}

然后执行 npm run build可以看到 生成的dis/bundle.js

也可以省略 配置文件,rollup 会自动加载根目录下的rollup.config.js, rollup --config --bundleConfigAsCjs

多入口打包文件,配置文件可以是数组对象

会有一些多入口页面打包,通过配置入口,删除不同目录文件的编译资源

定义rollup.config.js文件

// rollup.config.jsexport default [    {        input: "main.js",        output: {            file: "dist/bundle.js",            format: "iife",        }    },    {        input: "login.js",        output: {            file: "dist/login.js",            format: "iife",        }    }],

如果想要输出多个类型的编译资源output配置为数组

// rollup.config.jsexport default [    {        input: "main.js",        output: [            {                file: "dist/bundle.js",                format: "iife",            },            {                file: "dist/bundle-es.js",                format: "es",            },            {                file: "dist/bundle-cjs.js",                format: "cjs",            }        ]    },],

可异步请求配置文件

如果是在线配置,存储在后端。可通过请求获取配置文件。

// rollup.config.jsimport ajax from "libs/ajax";export default ajax.get("/**/**/rolleup-config");

多接口、都入口配置,则改为

// rollup.config.jsimport ajax from "libs/ajax";export default Promise.all([  ajax.get("/**/**/rolleup-config-main"),  ajax.get("/**/**/rolleup-config-login"),]);

通过命令行参数适用不同的配置文件

开发坏境和生产环境有不同的配置。通过命令行参数,使用对应的配置文件。

// rollup.config.jsimport devConfig from "./build/rollup.dev.config.js";import prdConfig from "./build/rollup.prd.config.js";export default (commandLineArgs) => {  if (commandLineArgs.environment === "dev") {    return devConfig;  }  return prdConfig;};

修改package.json提供 dev、build 脚本

{  "scripts": {    "test": "echo \"Error: no test specified\" && exit 1",    "dev": "rollup --config --environment dev --bundleConfigAsCjs",    "build": "rollup --config --bundleConfigAsCjs --environment prd"  }}

rollup.config.js配置文件说明

// rollup.config.js// can be an array (for multiple inputs)export default {  // core input options  external,  input: "main.js", // 主入口文件配置路径  plugins, // 使用插件,  // advanced input options  cache,  onwarn,  preserveEntrySignatures,  strictDeprecations,  // danger zone  acorn,  acornInjectPlugins,  context,  moduleContext,  preserveSymlinks,  shimMissingExports,  treeshake,  // experimental  experimentalCacheExpiry,  perf,  // required (can be an array, for multiple outputs)  output: {    // core output options    dir: "dist", // 编译文件目录地址,多个编译文件则必须指定    file: "dist/bundle.js", // 编译后文件目录路径    format, // 文件编译类型 es cjs iife    globals,    name,    plugins, // 针对某些输出的插件    // advanced output options    assetFileNames,    banner,    chunkFileNames,    compact,    entryFileNames,    extend,    footer,    hoistTransitiveImports,    inlineDynamicImports,    interop,    intro,    manualChunks,    minifyInternalExports,    outro,    paths,    preserveModules,    preserveModulesRoot,    sourcemap,    sourcemapBaseUrl,    sourcemapExcludeSources,    sourcemapFile,    sourcemapPathTransform,    validate,    // danger zone    amd,    esModule,    exports,    externalLiveBindings,    freeze,    indent,    namespaceToStringTag,    noConflict,    preferConst,    sanitizeFileName,    strict,    systemNullSetters,  },  watch: {    buildDelay,    chokidar,    clearScreen,    skipWrite,    exclude,    include,  },};

使用一个加载json文件的插件

安装

$> npm i --save-dev @rollup/plugin-json

在配置中使用插件

// rollup.config.js prdimport PluginJson from "@rollup/plugin-json";export default {  input: "main.js",  output: {    file: "dist/bundle.js",    format: "iife",  },  plugins: [PluginJson()],};

然后在项目中可以导入 JSON 文件,按对象取值。

import { version } from "./package.json";// import packageJson from "./package.json";console.log(version);

可以针对输出output配置插件

最小化构建代码,压缩代码,安装@rollup/plugin-terser

$> npm install --save-dev @rollup/plugin-terser

修改配置文件,在编译类型为 es 的输出使用插件

// rollup.config.js devimport PluginJson from "@rollup/plugin-json";import PluginTerser from "@rollup/plugin-terser";export default {  input: "main.js",  output: [    {      file: "dist/bundle.js",      format: "iife",    },    {      file: "dist/bundle-es.js",      format: "es",      plugins: [PluginTerser()],    },    {      file: "dist/bundle-cjs.js",      format: "cjs",    },  ],  plugins: [PluginJson()],};

执行npm run build可以看到bundle-es.js文件代码被压缩,没有任何格式

动态加载已使用代码拆分

在以下情况会自动进行代码拆分

  • 动态加载模块
  • 多入口引入统一模块。
  • 通过输出配置output.manualChunks指定需要拆分的模块

[!] RollupError: Invalid value "iife" for option "output.format" - UMD and IIFE output formats are not supported for code-splitting builds.

编译类型 UMD、IIFE 是不支持代码拆分的。改用 cjs

实现login模块的拆分,创建 login 文件入口。然后在 main.js 文件中动态引入

import("./login.js").then(() => console.log("成功加载login..."));

需要修改配置指定编译目录dir:"dist",原来指定的 file只是编译生成一个文件包。现在拆分代码,会生成多个编译包。

// rollup.config.js prdimport PluginJson from "@rollup/plugin-json";export default {  input: "main.js",  output: {    // file: "dist/bundle.js",    format: "cjs",    dir: "dist",  },  plugins: [PluginJson()],};

定义插件,以满足定制化需求

编译时可能会需要一些定制化处理。通过自定义插件实现代码的转换。

示例实现一个移除console.log的代码。一个插件约束

  • 插件名需要以rollup-plugin-**开头
  • package.json 中包含 rollup-plugin 关键字,构建后发布之前需要加前缀
  • 经过全面的测试。
  • 插件中尽可能的使用英文说明。
  • 尽可能的使用异步方法读取文件,比如使用 fs.readFile 而不是 fs.readFileSync
  • 插件是虚拟模块时,前缀追加\0.以便其他插件不去处理它。

项目目录下创建存储插件的位置 plugins/rollup-plugin-clear-console.js

// rollup-plugin-clear-consoleimport { createFilter } from "@rollup/pluginutils";export default function clearConsole(options = {}) {  // filter file  var filter = createFilter(options.include, options.exclude);  return {    name: "clear-console",    transform(code, id) {      /**       * code 为加载的文件内容       * id 为当前内容文件的路径地址,通过filter判断是否符合处理的要求       */      if (!filter(id)) return;      try {        return {          code: code.replace(/console\.log(\w*)/gi, ""),          map: { mappings: "" },        };      } catch (err) {        var message = "An error occurred during processing";        this.error({ message: message, id: id, cause: err });        return null;      }    },  };}

@rollup/pluginutils是针对编写 rollup 插件封装的一些功能性的函数,比如示例中使用了createFilter,可以帮助过滤指定的文件、排除指定文件。

rollup.config.dev.js使用自定义插件,并制定处理目录下为main.js的文件。

// rollup.config.js prdimport PluginJson from "@rollup/plugin-json";// 自定义插件import PluginClearConsole from "../plugins/rollup-plugin-clear-console";export default {  input: "main.js",  output: {    // file: "dist/bundle.js",    format: "cjs",    dir: "dist",  },  plugins: [    PluginJson(),    PluginClearConsole({      include: ["**/main.js"],    }),  ],};

然后执行脚本,看看效果npm run dev

dis/main.js文件中可以看到所有的console.log都被移除。而且由于移除这些代码,一些导入的变量未被使用,也被 tree shaking 了。

可以看到拆包编译的login.js文件中还是包含有console.log代码的。

配置一起使用vue

需要安装的 vue 相关的插件, 在 rollup-awesome 官方推荐的组件库

$> npm install rollup-plugin-vue vue --save-dev

安装的都是最新版本,vue 版本为3.2.45

创建 src 目录,用于 vue 视图组件的存放位置。

// index.jsimport { createApp } from "vue";import App from "./App.vue";const app = createApp(App);app.mount("#app");

在项目目录下创建 index.html 文件

                  rollup-vue2        
<script src="./dist/index.js"></script>

修改 rollup 配置文件rollup.config.dev.js

// rollup.config.dev.js devimport PluginJson from "@rollup/plugin-json";import PluginVue from "rollup-plugin-vue";// 自定义插件import PluginClearConsole from "../plugins/rollup-plugin-clear-console";export default {  input: "./src/index.js",  output: {    // file: "dist/bundle.js",    format: "es",    dir: "dist",  },  plugins: [    PluginVue(),    PluginJson(),    PluginClearConsole({      include: ["**/main.js"],    }),  ],};

然后执行 npm run dev ,打包编译后,通过live server启动一个服务访问 index.html

服务启动页面不展示问题

  1. 页面打开后没有任何展示,控制台报错 Cannot use import statement outside a module,查看编译包./dist/index.js. 没有将 vue 一起打包进去。加载不到

解决,安装依赖@rollup/plugin-node-resolve,将 vue 一起编译进去。

$> npm install @rollup/plugin-node-resolve --save-dev

修改配置,引入插件。 可以将 node_modules 中的组件包引入打包进编译包。

// rollup.config.dev.js devimport PluginNodeResolve from "@rollup/plugin-node-resolve";export default {  // ... other  plugins: [    // ... other    PluginNodeResolve(),  ],};
  1. 可以看到编译包变大了,vue 已经打包进去了,但是页面还不展示,报错Uncaught ReferenceError: process is not defined, 查看编译包./dist/index.js,引用全局变量process.env.NODE_ENV没有定义

解决,安装插件 @rollup/plugin-replace

$> npm install @rollup/plugin-replace --save-dev

修改配置,引入插件。 编译后替换编译包中的目标字符串。

// rollup.config.dev.js devimport PluginReplace from "@rollup/plugin-replace";export default {  // ... other  plugins: [    // ... other    PluginReplace({      "process.env.NODE_ENV": JSON.stringify("development"),      preventAssignment: true,    }),  ],};

页面打开展示正常。

生成 html 文件,npm run dev创建一个服务

为了达到开发的目的,需要自动生成 html 文件,自动注入人编译后的资源包。还有其他资源的解析、加载等。

生成 html 文件

安装依赖插件,生成 index.html,并将所有编译的资源包添加到页面上。

$> npm install @rollup/plugin-html --save-dev

使用插件

// rollup.config.dev.js devimport PluginHtml from "@rollup/plugin-html";export default {  // ... other  plugins: [    // ... other    PluginHtml({      title: "rollup-vue3",      fileName: "index.html",    }),  ],};

开发模式,启动 serve 服务

安装依赖插件,启动一个服务

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

使用插件

// rollup.config.dev.js devimport PluginServe from "rollup-plugin-serve";export default {  // ... other  plugins: [    // ... other    PluginServe({      // 运行在浏览器中      open: true,      // 运行成功后,打开的地址      openPage: "/",      // 打印服务地址      verbose: true,      // 地址,端口号      // host:"::",      host: "127.0.0.1",      port: 8009,      // https 协议配置      // https: {},      // 运行成功,事件      onListening: function (server) {        const address = server.address();        const host = address.address === "::" ? "localhost" : address.address;        // by using a bound function, we can access options as `this`        const protocol = this.https ? "https" : "http";        console.log(          `Server listening at ${protocol}://${host}:${address.port}/`        );      },    }),  ],};

运行成功后,未自动打开浏览器,serve 配置中的 open、openPage 暂时没有发现其作用设置"::"不生效,设置为“127.0.0.1” 启动后正常打开。

--watch监听模式,开发是文件变动重新编译

服务虽然启动了,但也仅仅是一个静态资源的服务,在开发的时候,通常需要实时编译改动的文件,希望立刻看到变化

修改启动脚本,在监听模式下,文件发生更改,就会重新编译。--watch 等同于 -w

{  "scripts": {    "test": "echo \"Error: no test specified\" && exit 1",  - "dev": "rollup --config --environment dev --bundleConfigAsCjs -w",  + "dev": "rollup --config --environment dev --bundleConfigAsCjs",  },}

虽然重新编译了,但是浏览器中还是需要手动刷新才能看到变化。--需要唤起浏览器服务的插件--

解析.vue中的样式 style

在 App.vue 中书写了样式,发现在页面中没有生效

增加插件postcss \ rollup-plugin-postcss

$> npm i postcss rollup-plugin-postcss -D

配置rollup.config.dev.js

import PluginPostCss from "rollup-plugin-postcss";export default {  //...  plugins: [    //...    PluginPostCss(),  ],};

重新运行,可以看到样式生效了。默认编译后的 css 样式是注入到 html 的 head 中。

使用预编译 less

安装 less

$> npm i less -D

即可直接使用

支持 JSX 语法

比较喜欢 jsx 语法的书写方式,实现相关配置;

import { defineComponent } from "vue";export default defineComponent({  name: "IFunLazySelect",  render() {    return (      
{/* 相关代码 */}
})

安装 @vue/babel-plugin-jsx, 还需要安装@babel/core 、@babel/preset-env

$> npm install @vue/babel-plugin-jsx @babel/core @babel/preset-env -D

新建.babelrc.js,配置

module.exports = {  presets: [["@babel/env", { modules: false }]],  plugins: ["@vue/babel-plugin-jsx"],};

这只是 babel 配置,还需要集成到 rollup 中,使之生效,安装@rollup/plugin-babel

则需要修改rollup.config.base.js,增加插件配置。

// rollup.config.base.jsimport PluginBabel from "@rollup/plugin-babel";export default {  plugins: [    // ... other    PluginBabel({ babelHelpers: "bundled" }),  ],};

重新启动项目,完美运行。

其他插件

  1. 解析 commonJS 模块,转换成 es6 模块。安装依赖
$> npm install @rollup/plugin-commonjs --save-dev

修改配置

// rollup.config.dev.js devimport PluginCommonJS from "@rollup/plugin-commonjs";export default {  // ... other  plugins: [    // ... other    PluginCommonJS(),  ],};
  1. 全局注入,比如使用 jquery,安装依赖
$> npm install @rollup/plugin-inject --save-dev

修改配置

// rollup.config.dev.js devimport PluginInject from "@rollup/plugin-inject";export default {  // ... other  plugins: [    // ... other    PluginInject({      $: "jquery",    }),  ],};
  1. 定义别名路径,比如通常使用@代替./src路径
$> npm install @rollup/plugin-alias --save-dev

修改配置

// rollup.config.dev.js devimport PluginAlias from "@rollup/plugin-alias";export default {  // ... other  plugins: [    // ... other    PluginAlias({      entries: {        "@": "../src",        libs: "../libs",      },    }),  ],};
  1. 加载图片资源,.png\.jpeg\.svg
$> npm install @rollup/plugin-image --save-dev

修改配置

// rollup.config.dev.js devimport PluginImage from "@rollup/plugin-image";export default {  // ... other  plugins: [    // ... other    PluginImage(),  ],};

关键词: