Rollup 配置 #

配置文件结构 #

基本结构 #

javascript
// rollup.config.js
export default {
  // 核心配置
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'es'
  },
  
  // 插件配置
  plugins: [],
  
  // 高级配置
  external: [],
  onwarn: (warning) => {},
  cache: true,
  
  // 监听配置
  watch: {}
};

配置类型定义 #

typescript
interface RollupOptions {
  input: InputOption;
  output: OutputOptions | OutputOptions[];
  plugins?: Plugin[];
  external?: ExternalOption;
  onwarn?: WarningHandler;
  cache?: boolean | RollupCache;
  watch?: WatcherOptions;
  maxParallelFileOps?: number;
  preserveEntrySignatures?: PreserveEntrySignaturesOption;
  shimMissingExports?: boolean;
  treeshake?: TreeshakeOptions | boolean;
  context?: string;
  moduleContext?: ((id: string) => string) | { [id: string]: string };
}

输入配置(input) #

字符串形式 #

javascript
export default {
  input: 'src/main.js'
};

数组形式 #

javascript
export default {
  input: ['src/main.js', 'src/admin.js']
};

对象形式 #

javascript
export default {
  input: {
    main: 'src/main.js',
    admin: 'src/admin.js',
    vendor: 'src/vendor.js'
  }
};

带选项的输入 #

javascript
export default {
  input: {
    main: {
      import: 'src/main.js',
      preserveSignature: 'strict'
    }
  }
};

输出配置(output) #

完整输出选项 #

javascript
export default {
  output: {
    // 基础选项
    file: 'dist/bundle.js',
    format: 'es',
    name: 'MyLibrary',
    
    // 文件命名
    assetFileNames: 'assets/[name]-[hash][extname]',
    chunkFileNames: 'chunks/[name]-[hash].js',
    entryFileNames: '[name].js',
    
    // Source Map
    sourcemap: true,
    sourcemapBaseUrl: 'https://example.com/maps/',
    sourcemapExcludeSources: false,
    sourcemapFile: 'dist/bundle.js.map',
    sourcemapPathTransform: (relativePath) => `src/${relativePath}`,
    
    // 代码注入
    banner: '/* My Library v1.0.0 */',
    footer: '/* End of library */',
    intro: 'var ENV = "production";',
    outro: 'console.log("Library loaded");',
    
    // 格式化
    compact: false,
    extend: false,
    exports: 'auto',
    interop: 'auto',
    
    // 依赖
    globals: { lodash: '_' },
    
    // 模块保留
    preserveModules: false,
    preserveModulesRoot: 'src',
    
    // 其他
    hoistTransitiveImports: true,
    minifyInternalExports: false,
    preferConst: false,
    generatedCode: { constBindings: false }
  }
};

输出格式详解 #

ES Module(es) #

javascript
output: {
  format: 'es',
  // 输出示例:
  // import { foo } from './foo.js';
  // export default function() { ... }
}

特点

  • 现代 JavaScript 模块格式
  • 支持 Tree-shaking
  • 浏览器和 Node.js 原生支持

CommonJS(cjs) #

javascript
output: {
  format: 'cjs',
  exports: 'auto',  // 'auto' | 'named' | 'default'
  // 输出示例:
  // 'use strict';
  // var foo = require('./foo.js');
  // module.exports = function() { ... }
}

特点

  • Node.js 模块格式
  • 兼容性好
  • 不支持 Tree-shaking

UMD(umd) #

javascript
output: {
  format: 'umd',
  name: 'MyLibrary',
  exports: 'auto',
  extend: false,  // 是否扩展全局变量
  amd: {
    id: 'my-library'  // AMD 模块 ID
  },
  // 输出示例:
  // (function (global, factory) {
  //   typeof exports === 'object' && typeof module !== 'undefined' ? factory() :
  //   typeof define === 'function' && define.amd ? define(factory) :
  //   (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.MyLibrary = factory());
  // })(this, (function () { ... }));
}

特点

  • 通用模块定义
  • 支持 AMD、CommonJS、全局变量
  • 适用于库发布

IIFE(iife) #

javascript
output: {
  format: 'iife',
  name: 'MyApp',
  extend: false,
  // 输出示例:
  // var MyApp = (function () {
  //   'use strict';
  //   // ...代码
  // })();
}

特点

  • 立即执行函数
  • 适合浏览器直接使用
  • 不需要模块系统

System(system) #

javascript
output: {
  format: 'system',
  // 输出示例:
  // System.register('my-lib', [], function (exports) {
  //   'use strict';
  //   return { execute: function () { ... } };
  // });
}

特点

  • SystemJS 模块格式
  • 支持动态加载

文件命名模板 #

javascript
output: {
  // 入口文件命名
  entryFileNames: '[name].js',
  // 可用占位符:
  // [name] - 入口名称
  // [hash] - 内容哈希
  // [format] - 输出格式
  
  // 代码块命名
  chunkFileNames: 'chunks/[name]-[hash].js',
  
  // 静态资源命名
  assetFileNames: 'assets/[name]-[hash][extname]'
}

多输出配置 #

javascript
export default {
  input: 'src/index.js',
  output: [
    {
      file: 'dist/my-lib.cjs.js',
      format: 'cjs',
      sourcemap: true
    },
    {
      file: 'dist/my-lib.esm.js',
      format: 'es',
      sourcemap: true
    },
    {
      file: 'dist/my-lib.umd.js',
      format: 'umd',
      name: 'MyLib',
      sourcemap: true,
      globals: { lodash: '_' }
    }
  ]
};

外部依赖配置(external) #

数组形式 #

javascript
export default {
  external: [
    'lodash',
    'axios',
    'vue',
    'vue-router'
  ]
};

正则表达式 #

javascript
export default {
  external: [
    /^lodash/,
    /^@vue/,
    /^@my-org\//
  ]
};

函数形式 #

javascript
export default {
  external: (id, parentId, isResolved) => {
    // id: 模块 ID
    // parentId: 父模块 ID
    // isResolved: 是否已解析
    
    // 排除所有 node_modules
    if (id.includes('node_modules')) {
      return true;
    }
    
    // 排除特定模块
    if (id === 'lodash' || id.startsWith('lodash/')) {
      return true;
    }
    
    return false;
  }
};

对象形式 #

javascript
export default {
  external: {
    lodash: '_',
    jquery: '$',
    axios: 'axios'
  }
};

排除 Node.js 内置模块 #

javascript
import { builtinModules } from 'module';

export default {
  external: [
    ...builtinModules,
    ...builtinModules.map(m => `node:${m}`)
  ]
};

插件配置(plugins) #

基本用法 #

javascript
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import terser from '@rollup/plugin-terser';

export default {
  plugins: [
    resolve(),
    commonjs(),
    terser()
  ]
};

插件顺序 #

插件执行顺序很重要:

javascript
export default {
  plugins: [
    // 1. 解析模块
    resolve(),
    
    // 2. 转换 CommonJS
    commonjs(),
    
    // 3. 转换 TypeScript
    typescript(),
    
    // 4. 处理 JSON
    json(),
    
    // 5. 其他转换
    babel({ babelHelpers: 'bundled' }),
    
    // 6. 压缩(最后执行)
    terser()
  ]
};

条件插件 #

javascript
const isProduction = process.env.NODE_ENV === 'production';

export default {
  plugins: [
    resolve(),
    commonjs(),
    isProduction && terser()
  ].filter(Boolean)
};

插件配置选项 #

javascript
import resolve from '@rollup/plugin-node-resolve';

export default {
  plugins: [
    resolve({
      browser: true,
      dedupe: ['vue'],
      extensions: ['.js', '.jsx', '.ts', '.tsx'],
      mainFields: ['browser', 'module', 'main'],
      preferBuiltins: false
    })
  ]
};

高级配置选项 #

preserveEntrySignatures #

控制入口导出的保留方式:

javascript
export default {
  input: 'src/main.js',
  preserveEntrySignatures: 'strict',  // 'strict' | 'allow-extension' | false
  output: {
    format: 'es'
  }
};
描述
'strict' 保留所有入口导出(默认)
'allow-extension' 允许移除未使用的导出
false 不保留入口导出

shimMissingExports #

为缺失的导出创建 shim:

javascript
export default {
  input: 'src/main.js',
  shimMissingExports: true
};

// 缺失的导出会被替换为 undefined

treeshake #

Tree-shaking 配置:

javascript
export default {
  treeshake: {
    annotations: true,           // 使用注释标记
    moduleSideEffects: true,     // 模块副作用
    propertyReadSideEffects: true,
    tryCatchDeoptimization: true,
    unknownGlobalSideEffects: true
  }
};

context #

设置 this 的值:

javascript
export default {
  context: 'window'
};

moduleContext #

为特定模块设置 this

javascript
export default {
  moduleContext: {
    'src/legacy.js': 'window',
    'src/node-script.js': 'global'
  }
};

onwarn #

自定义警告处理:

javascript
export default {
  onwarn: (warning, warn) => {
    // 忽略特定警告
    if (warning.code === 'THIS_IS_UNDEFINED') {
      return;
    }
    
    // 自定义处理
    if (warning.code === 'CIRCULAR_DEPENDENCY') {
      console.log('Circular dependency detected:', warning.message);
      return;
    }
    
    // 使用默认处理
    warn(warning);
  }
};

cache #

启用/禁用缓存:

javascript
export default {
  cache: true  // 默认 true
};

maxParallelFileOps #

最大并行文件操作数:

javascript
export default {
  maxParallelFileOps: 20  // 默认 20
};

监听配置(watch) #

基本配置 #

javascript
export default {
  watch: {
    buildDelay: 300,
    clearScreen: true,
    skipWrite: false,
    chokidar: {
      usePolling: true
    }
  }
};

监听选项详解 #

javascript
export default {
  watch: {
    // 构建延迟(毫秒)
    buildDelay: 300,
    
    // 是否清屏
    clearScreen: true,
    
    // 是否跳过写入文件
    skipWrite: false,
    
    // 包含的文件
    include: ['src/**'],
    
    // 排除的文件
    exclude: ['node_modules/**', 'dist/**'],
    
    // chokidar 选项
    chokidar: {
      usePolling: true,
      interval: 100,
      binaryInterval: 300,
      alwaysStat: false,
      ignoreInitial: true,
      awaitWriteFinish: {
        stabilityThreshold: 2000,
        pollInterval: 100
      }
    }
  }
};

完整配置示例 #

库开发配置 #

javascript
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import typescript from '@rollup/plugin-typescript';
import terser from '@rollup/plugin-terser';
import dts from 'rollup-plugin-dts';

const isProduction = process.env.NODE_ENV === 'production';

export default [
  // JavaScript 打包
  {
    input: 'src/index.ts',
    output: [
      {
        file: 'dist/my-lib.cjs.js',
        format: 'cjs',
        sourcemap: true,
        exports: 'named'
      },
      {
        file: 'dist/my-lib.esm.js',
        format: 'es',
        sourcemap: true
      },
      {
        file: 'dist/my-lib.umd.js',
        format: 'umd',
        name: 'MyLib',
        sourcemap: true,
        globals: {
          lodash: '_'
        }
      }
    ],
    external: ['lodash', 'axios'],
    plugins: [
      resolve({
        extensions: ['.ts', '.js']
      }),
      commonjs(),
      typescript({
        tsconfig: './tsconfig.json'
      }),
      isProduction && terser()
    ].filter(Boolean)
  },
  // 类型声明文件
  {
    input: 'dist/types/index.d.ts',
    output: {
      file: 'dist/my-lib.d.ts',
      format: 'es'
    },
    plugins: [dts()]
  }
];

应用开发配置 #

javascript
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import babel from '@rollup/plugin-babel';
import terser from '@rollup/plugin-terser';
import livereload from 'rollup-plugin-livereload';
import serve from 'rollup-plugin-serve';

const isProduction = process.env.NODE_ENV === 'production';

export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife',
    name: 'App',
    sourcemap: !isProduction,
    banner: '// My App v1.0.0'
  },
  plugins: [
    resolve({
      browser: true
    }),
    commonjs(),
    babel({
      babelHelpers: 'bundled',
      exclude: 'node_modules/**'
    }),
    !isProduction && serve({
      contentBase: 'dist',
      port: 3000
    }),
    !isProduction && livereload({
      watch: 'dist'
    }),
    isProduction && terser()
  ].filter(Boolean),
  watch: {
    clearScreen: false
  }
};

组件库配置 #

javascript
import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import typescript from '@rollup/plugin-typescript';
import postcss from 'rollup-plugin-postcss';
import vue from 'rollup-plugin-vue';

export default {
  input: 'src/components/index.ts',
  output: {
    dir: 'dist',
    format: 'es',
    preserveModules: true,
    preserveModulesRoot: 'src',
    sourcemap: true
  },
  external: ['vue', 'vue-router'],
  plugins: [
    resolve({
      extensions: ['.ts', '.js', '.vue']
    }),
    commonjs(),
    vue(),
    typescript(),
    postcss({
      extract: true,
      minimize: true
    })
  ]
};

配置文件高级用法 #

动态配置 #

javascript
export default async () => {
  const pkg = await import('./package.json', { assert: { type: 'json' } });
  
  return {
    input: 'src/index.js',
    output: {
      file: 'dist/bundle.js',
      format: 'es',
      banner: `// ${pkg.name} v${pkg.version}`
    }
  };
};

环境变量配置 #

javascript
const env = process.env.NODE_ENV || 'development';
const config = require(`./config/${env}.json`);

export default {
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'iife',
    intro: `var CONFIG = ${JSON.stringify(config)};`
  }
};

多环境配置 #

javascript
// rollup.config.js
const configs = {
  development: {
    input: 'src/main.js',
    output: {
      file: 'dist/bundle.js',
      format: 'iife',
      sourcemap: true
    }
  },
  production: {
    input: 'src/main.js',
    output: {
      file: 'dist/bundle.min.js',
      format: 'iife',
      sourcemap: false
    },
    plugins: [terser()]
  }
};

export default configs[process.env.NODE_ENV || 'development'];

配置验证 #

类型检查 #

typescript
import type { RollupOptions } from 'rollup';

const config: RollupOptions = {
  input: 'src/main.ts',
  output: {
    file: 'dist/bundle.js',
    format: 'es'
  }
};

export default config;

配置验证函数 #

javascript
function validateConfig(config) {
  if (!config.input) {
    throw new Error('Missing input configuration');
  }
  
  if (!config.output) {
    throw new Error('Missing output configuration');
  }
  
  if (config.output.format && !['es', 'cjs', 'umd', 'iife', 'system'].includes(config.output.format)) {
    throw new Error(`Invalid format: ${config.output.format}`);
  }
  
  return config;
}

export default validateConfig({
  input: 'src/main.js',
  output: {
    file: 'dist/bundle.js',
    format: 'es'
  }
});

下一步 #

现在你已经深入了解了 Rollup 的配置选项,接下来学习 插件系统 掌握如何扩展 Rollup 的功能!

最后更新:2026-03-28