From 6ed8e286f149f9474e0fc624110de5f787551d62 Mon Sep 17 00:00:00 2001 From: Evan You Date: Sun, 10 Jan 2021 18:19:09 -0500 Subject: [PATCH] feat: allow passing options to rollup commonjs plugin via build.commonjsOptions close #1460 --- docs/config/index.md | 6 + packages/vite/src/node/build.ts | 15 ++- packages/vite/src/node/index.ts | 1 + packages/vite/src/node/optimizer/index.ts | 5 +- packages/vite/types/commonjs.d.ts | 152 ++++++++++++++++++++++ 5 files changed, 171 insertions(+), 8 deletions(-) create mode 100644 packages/vite/types/commonjs.d.ts diff --git a/docs/config/index.md b/docs/config/index.md index 1ace65ae99990c..f7869cc9bd2c27 100644 --- a/docs/config/index.md +++ b/docs/config/index.md @@ -362,6 +362,12 @@ export default ({ command, mode }) => { Directly customize the underlying Rollup bundle. This is the same as options that can be exported from a Rollup config file and will be merged with Vite's internal Rollup options. See [Rollup options docs](https://rollupjs.org/guide/en/#big-list-of-options) for more details. +### build.commonjsOptions + +- **Type:** [`RollupCommonJSOptions`](https://github.com/rollup/plugins/tree/master/packages/commonjs#options) + + Options to pass on to [@rollup/plugin-commonjs](https://github.com/rollup/plugins/tree/master/packages/commonjs). This applies to dependency pre-bundling as well. + ### build.lib - **Type:** `{ entry: string, name?: string, formats?: ('es' | 'cjs' | 'umd' | 'iife')[] }` diff --git a/packages/vite/src/node/build.ts b/packages/vite/src/node/build.ts index 218af27c73fffb..6417c4eb0dc0bb 100644 --- a/packages/vite/src/node/build.ts +++ b/packages/vite/src/node/build.ts @@ -20,6 +20,7 @@ import { Terser } from 'types/terser' import { copyDir, emptyDir, lookupFile } from './utils' import { manifestPlugin } from './plugins/manifest' import commonjsPlugin from '@rollup/plugin-commonjs' +import { RollupCommonJSOptions } from 'types/commonjs' import dynamicImportVars from '@rollup/plugin-dynamic-import-vars' import { Logger } from './logger' import { TransformOptions } from 'esbuild' @@ -108,6 +109,10 @@ export interface BuildOptions { * https://rollupjs.org/guide/en/#big-list-of-options */ rollupOptions?: RollupOptions + /** + * Options to pass on to `@rollup/plugin-commonjs` + */ + commonjsOptions?: RollupCommonJSOptions /** * Whether to write bundle to disk * @default true @@ -162,6 +167,11 @@ export function resolveBuildOptions( cssCodeSplit: !raw?.lib, sourcemap: false, rollupOptions: {}, + commonjsOptions: { + include: [/node_modules/], + extensions: ['.js', '.cjs'], + ...raw?.commonjsOptions + }, minify: 'terser', terserOptions: {}, cleanCssOptions: {}, @@ -199,10 +209,7 @@ export function resolveBuildPlugins( return { pre: [ buildHtmlPlugin(config), - commonjsPlugin({ - include: [/node_modules/], - extensions: ['.js', '.cjs'] - }), + commonjsPlugin(options.commonjsOptions), dataURIPlugin(), buildDefinePlugin(config), dynamicImportVars({ diff --git a/packages/vite/src/node/index.ts b/packages/vite/src/node/index.ts index b7b8d7dd66f892..84c00584644bdc 100644 --- a/packages/vite/src/node/index.ts +++ b/packages/vite/src/node/index.ts @@ -47,3 +47,4 @@ export type { HttpProxy } from 'types/http-proxy' export type { FSWatcher, WatchOptions } from 'types/chokidar' export type { Terser } from 'types/terser' export type { CleanCSS } from 'types/clean-css' +export type { RollupCommonJSOptions } from 'types/commonjs' diff --git a/packages/vite/src/node/optimizer/index.ts b/packages/vite/src/node/optimizer/index.ts index 3e682f1182c6b3..18307d86cce9d2 100644 --- a/packages/vite/src/node/optimizer/index.ts +++ b/packages/vite/src/node/optimizer/index.ts @@ -195,10 +195,7 @@ export async function optimizeDeps( namedExports: true }), ...normal, - commonjsPlugin({ - include: [/node_modules/], - extensions: ['.js', '.cjs'] - }), + commonjsPlugin(config.build.commonjsOptions), buildDefinePlugin(config), depAssetRewritePlugin(config), recordCjsEntryPlugin(data), diff --git a/packages/vite/types/commonjs.d.ts b/packages/vite/types/commonjs.d.ts new file mode 100644 index 00000000000000..e6adaf0a0739b1 --- /dev/null +++ b/packages/vite/types/commonjs.d.ts @@ -0,0 +1,152 @@ +/** + * https://github.com/rollup/plugins/blob/master/packages/commonjs/types/index.d.ts + * + * This source code is licensed under the MIT license found in the + * LICENSE file at + * https://github.com/rollup/plugins/blob/master/LICENSE + */ + +type FilterPattern = string | RegExp | readonly (string | RegExp)[] + +type RequireReturnsDefaultOption = boolean | 'auto' | 'preferred' | 'namespace' + +export interface RollupCommonJSOptions { + /** + * A minimatch pattern, or array of patterns, which specifies the files in + * the build the plugin should operate on. By default, all files with + * extension `".cjs"` or those in `extensions` are included, but you can narrow + * this list by only including specific files. These files will be analyzed + * and transpiled if either the analysis does not find ES module specific + * statements or `transformMixedEsModules` is `true`. + * @default undefined + */ + include?: FilterPattern + /** + * A minimatch pattern, or array of patterns, which specifies the files in + * the build the plugin should _ignore_. By default, all files with + * extensions other than those in `extensions` or `".cjs"` are ignored, but you + * can exclude additional files. See also the `include` option. + * @default undefined + */ + exclude?: FilterPattern + /** + * For extensionless imports, search for extensions other than .js in the + * order specified. Note that you need to make sure that non-JavaScript files + * are transpiled by another plugin first. + * @default [ '.js' ] + */ + extensions?: ReadonlyArray + /** + * If true then uses of `global` won't be dealt with by this plugin + * @default false + */ + ignoreGlobal?: boolean + /** + * If false, skips source map generation for CommonJS modules. This will improve performance. + * @default true + */ + sourceMap?: boolean + /** + * Instructs the plugin whether to enable mixed module transformations. This + * is useful in scenarios with modules that contain a mix of ES `import` + * statements and CommonJS `require` expressions. Set to `true` if `require` + * calls should be transformed to imports in mixed modules, or `false` if the + * `require` expressions should survive the transformation. The latter can be + * important if the code contains environment detection, or you are coding + * for an environment with special treatment for `require` calls such as + * ElectronJS. See also the `ignore` option. + * @default false + */ + transformMixedEsModules?: boolean + /** + * Sometimes you have to leave require statements unconverted. Pass an array + * containing the IDs or a `id => boolean` function. + * @default [] + */ + ignore?: ReadonlyArray | ((id: string) => boolean) + /** + * Controls how to render imports from external dependencies. By default, + * this plugin assumes that all external dependencies are CommonJS. This + * means they are rendered as default imports to be compatible with e.g. + * NodeJS where ES modules can only import a default export from a CommonJS + * dependency. + * + * If you set `esmExternals` to `true`, this plugins assumes that all + * external dependencies are ES modules and respect the + * `requireReturnsDefault` option. If that option is not set, they will be + * rendered as namespace imports. + * + * You can also supply an array of ids to be treated as ES modules, or a + * function that will be passed each external id to determine if it is an ES + * module. + * @default false + */ + esmExternals?: boolean | ReadonlyArray | ((id: string) => boolean) + /** + * Controls what is returned when requiring an ES module from a CommonJS file. + * When using the `esmExternals` option, this will also apply to external + * modules. By default, this plugin will render those imports as namespace + * imports i.e. + * + * ```js + * // input + * const foo = require('foo'); + * + * // output + * import * as foo from 'foo'; + * ``` + * + * However there are some situations where this may not be desired. + * For these situations, you can change Rollup's behaviour either globally or + * per module. To change it globally, set the `requireReturnsDefault` option + * to one of the following values: + * + * - `false`: This is the default, requiring an ES module returns its + * namespace. This is the only option that will also add a marker + * `__esModule: true` to the namespace to support interop patterns in + * CommonJS modules that are transpiled ES modules. + * - `"namespace"`: Like `false`, requiring an ES module returns its + * namespace, but the plugin does not add the `__esModule` marker and thus + * creates more efficient code. For external dependencies when using + * `esmExternals: true`, no additional interop code is generated. + * - `"auto"`: This is complementary to how `output.exports: "auto"` works in + * Rollup: If a module has a default export and no named exports, requiring + * that module returns the default export. In all other cases, the namespace + * is returned. For external dependencies when using `esmExternals: true`, a + * corresponding interop helper is added. + * - `"preferred"`: If a module has a default export, requiring that module + * always returns the default export, no matter whether additional named + * exports exist. This is similar to how previous versions of this plugin + * worked. Again for external dependencies when using `esmExternals: true`, + * an interop helper is added. + * - `true`: This will always try to return the default export on require + * without checking if it actually exists. This can throw at build time if + * there is no default export. This is how external dependencies are handled + * when `esmExternals` is not used. The advantage over the other options is + * that, like `false`, this does not add an interop helper for external + * dependencies, keeping the code lean. + * + * To change this for individual modules, you can supply a function for + * `requireReturnsDefault` instead. This function will then be called once for + * each required ES module or external dependency with the corresponding id + * and allows you to return different values for different modules. + * @default false + */ + requireReturnsDefault?: + | RequireReturnsDefaultOption + | ((id: string) => RequireReturnsDefaultOption) + /** + * Some modules contain dynamic `require` calls, or require modules that + * contain circular dependencies, which are not handled well by static + * imports. Including those modules as `dynamicRequireTargets` will simulate a + * CommonJS (NodeJS-like) environment for them with support for dynamic and + * circular dependencies. + * + * Note: In extreme cases, this feature may result in some paths being + * rendered as absolute in the final bundle. The plugin tries to avoid + * exposing paths from the local machine, but if you are `dynamicRequirePaths` + * with paths that are far away from your project's folder, that may require + * replacing strings like `"/Users/John/Desktop/foo-project/"` -> `"/"`. + */ + dynamicRequireTargets?: string | ReadonlyArray +}