From e3ae259b4e8f8944b31c28d8f9acaeab5831166d Mon Sep 17 00:00:00 2001 From: Lukas Taegert-Atkinson Date: Mon, 1 Apr 2019 07:07:38 +0200 Subject: [PATCH] Add option to configure import.meta.url resolution --- docs/999-big-list-of-options.md | 27 ++++++++++++++++++- src/Chunk.ts | 4 ++- src/ast/nodes/MetaProperty.ts | 25 +++++++++-------- src/rollup/types.d.ts | 1 + src/utils/mergeOptions.ts | 1 + .../configure-import-meta-url/_config.js | 13 +++++++++ .../_expected/amd.js | 5 ++++ .../_expected/cjs.js | 3 +++ .../configure-import-meta-url/_expected/es.js | 1 + .../_expected/iife.js | 6 +++++ .../_expected/system.js | 10 +++++++ .../_expected/umd.js | 8 ++++++ .../samples/configure-import-meta-url/main.js | 1 + test/misc/optionList.js | 4 +-- 14 files changed, 94 insertions(+), 15 deletions(-) create mode 100644 test/form/samples/configure-import-meta-url/_config.js create mode 100644 test/form/samples/configure-import-meta-url/_expected/amd.js create mode 100644 test/form/samples/configure-import-meta-url/_expected/cjs.js create mode 100644 test/form/samples/configure-import-meta-url/_expected/es.js create mode 100644 test/form/samples/configure-import-meta-url/_expected/iife.js create mode 100644 test/form/samples/configure-import-meta-url/_expected/system.js create mode 100644 test/form/samples/configure-import-meta-url/_expected/umd.js create mode 100644 test/form/samples/configure-import-meta-url/main.js diff --git a/docs/999-big-list-of-options.md b/docs/999-big-list-of-options.md index 38736b1fcf7..6bff411623b 100755 --- a/docs/999-big-list-of-options.md +++ b/docs/999-big-list-of-options.md @@ -614,6 +614,31 @@ Default: `true` Whether to `Object.freeze()` namespace import objects (i.e. `import * as namespaceImportObject from...`) that are accessed dynamically. +#### output.importMetaUrl +Type: `((chunkId: string, moduleId: string) => string)`
+ +This allows the user to configure how Rollup handles `import.meta.url`. In ES modules, `import.meta.url` returns the URL of the current module, e.g. `http://server.net/bundle.js` for browsers or `file:///path/to/bundle.js` in Node. + +By default for formats other than ES modules, Rollup replaces `import.meta.url` with code that attempts to match this behaviour by returning the dynamic URL of the current chunk. Note that all formats except CommonJS and UMD assume that they run in a browser environment where `URL` and `document` are available. + + This behaviour can be customized by supplying a function, which will replace `import.meta.url` for all formats: + +```javascript +// rollup.config.js +export default { + ..., + output: { + ..., + + // this will use the original module id when resolving import.meta.url + importMetaUrl(chunkId, moduleId) { + return `"${moduleId}"`; + } + } +}; + +``` + #### output.indent Type: `boolean | string`
CLI: `--indent`/`--no-indent`
@@ -621,7 +646,7 @@ Default: `true` The indent string to use, for formats that require code to be indented (`amd`, `iife`, `umd`, `system`). Can also be `false` (no indent), or `true` (the default – auto-indent) -```js +```javascript // rollup.config.js export default { ..., diff --git a/src/Chunk.ts b/src/Chunk.ts index 4601b6d133d..144dc064997 100644 --- a/src/Chunk.ts +++ b/src/Chunk.ts @@ -800,7 +800,9 @@ export default class Chunk { const module = this.orderedModules[i]; const code = this.renderedModuleSources[i]; for (const importMeta of module.importMetas) { - if (importMeta.renderFinalMechanism(code, this.id, options.format)) usesMechanism = true; + if (importMeta.renderFinalMechanism(code, this.id, options.format, options.importMetaUrl)) { + usesMechanism = true; + } } } return usesMechanism; diff --git a/src/ast/nodes/MetaProperty.ts b/src/ast/nodes/MetaProperty.ts index 233aaae0d16..b49f5f732a1 100644 --- a/src/ast/nodes/MetaProperty.ts +++ b/src/ast/nodes/MetaProperty.ts @@ -22,6 +22,7 @@ const importMetaUrlMechanisms: Record string> = { `(require('u' + 'rl').URL)` )} : ${getUrlFromDocument(chunkId)})`, iife: chunkId => getUrlFromDocument(chunkId), + system: () => `module.meta.url`, umd: chunkId => `(typeof document === 'undefined' ? ${getResolveUrl( `'file:' + __filename`, @@ -68,12 +69,15 @@ export default class MetaProperty extends NodeBase { super.render(code, options); } - renderFinalMechanism(code: MagicString, chunkId: string, format: string): boolean { - if (!this.rendered) return false; + renderFinalMechanism( + code: MagicString, + chunkId: string, + format: string, + renderImportMetaUrl: ((chunkId: string, moduleId: string) => string) | void + ): boolean { + if (!this.included || !(this.parent instanceof MemberExpression)) return false; - if (this.parent instanceof MemberExpression === false) return false; - - const parent = this.parent; + const parent = this.parent; let importMetaProperty: string; if (parent.property instanceof Identifier) importMetaProperty = parent.property.name; @@ -89,12 +93,11 @@ export default class MetaProperty extends NodeBase { return true; } - if (format === 'system') { - code.overwrite(this.meta.start, this.meta.end, 'module'); - } else if (importMetaProperty === 'url') { - const importMetaUrlMechanism = importMetaUrlMechanisms[format]; - if (importMetaUrlMechanism) - code.overwrite(parent.start, parent.end, importMetaUrlMechanism(chunkId)); + if (importMetaProperty === 'url') { + const getImportMetaUrl = renderImportMetaUrl || importMetaUrlMechanisms[format]; + if (getImportMetaUrl) { + code.overwrite(parent.start, parent.end, getImportMetaUrl(chunkId, this.context.module.id)); + } return true; } diff --git a/src/rollup/types.d.ts b/src/rollup/types.d.ts index 2e64f739804..529e4a14ca7 100644 --- a/src/rollup/types.d.ts +++ b/src/rollup/types.d.ts @@ -315,6 +315,7 @@ export interface OutputOptions { format?: ModuleFormat; freeze?: boolean; globals?: GlobalsOption; + importMetaUrl?: (chunkId: string, moduleId: string) => string; indent?: boolean; interop?: boolean; intro?: string | (() => string | Promise); diff --git a/src/utils/mergeOptions.ts b/src/utils/mergeOptions.ts index 8f8c2629a98..8c6bd3d4856 100644 --- a/src/utils/mergeOptions.ts +++ b/src/utils/mergeOptions.ts @@ -248,6 +248,7 @@ function getOutputOptions( format: format === 'esm' ? 'es' : format, freeze: getOption('freeze', true), globals: getOption('globals'), + importMetaUrl: getOption('importMetaUrl'), indent: getOption('indent', true), interop: getOption('interop', true), intro: getOption('intro'), diff --git a/test/form/samples/configure-import-meta-url/_config.js b/test/form/samples/configure-import-meta-url/_config.js new file mode 100644 index 00000000000..8b37dddd4fa --- /dev/null +++ b/test/form/samples/configure-import-meta-url/_config.js @@ -0,0 +1,13 @@ +module.exports = { + description: 'allows to configure import.meta.url', + options: { + output: { + importMetaUrl(chunkId, moduleId) { + return `'${chunkId}/${moduleId + .split('/') + .slice(-2) + .join('/')}'`; + } + } + } +}; diff --git a/test/form/samples/configure-import-meta-url/_expected/amd.js b/test/form/samples/configure-import-meta-url/_expected/amd.js new file mode 100644 index 00000000000..a05f2631fd5 --- /dev/null +++ b/test/form/samples/configure-import-meta-url/_expected/amd.js @@ -0,0 +1,5 @@ +define(['module'], function (module) { 'use strict'; + + console.log('amd.js/configure-import-meta-url/main.js'); + +}); diff --git a/test/form/samples/configure-import-meta-url/_expected/cjs.js b/test/form/samples/configure-import-meta-url/_expected/cjs.js new file mode 100644 index 00000000000..a73c255c05e --- /dev/null +++ b/test/form/samples/configure-import-meta-url/_expected/cjs.js @@ -0,0 +1,3 @@ +'use strict'; + +console.log('cjs.js/configure-import-meta-url/main.js'); diff --git a/test/form/samples/configure-import-meta-url/_expected/es.js b/test/form/samples/configure-import-meta-url/_expected/es.js new file mode 100644 index 00000000000..a71014898e3 --- /dev/null +++ b/test/form/samples/configure-import-meta-url/_expected/es.js @@ -0,0 +1 @@ +console.log('es.js/configure-import-meta-url/main.js'); diff --git a/test/form/samples/configure-import-meta-url/_expected/iife.js b/test/form/samples/configure-import-meta-url/_expected/iife.js new file mode 100644 index 00000000000..d4aff63d317 --- /dev/null +++ b/test/form/samples/configure-import-meta-url/_expected/iife.js @@ -0,0 +1,6 @@ +(function () { + 'use strict'; + + console.log('iife.js/configure-import-meta-url/main.js'); + +}()); diff --git a/test/form/samples/configure-import-meta-url/_expected/system.js b/test/form/samples/configure-import-meta-url/_expected/system.js new file mode 100644 index 00000000000..f0105ea8de8 --- /dev/null +++ b/test/form/samples/configure-import-meta-url/_expected/system.js @@ -0,0 +1,10 @@ +System.register([], function (exports, module) { + 'use strict'; + return { + execute: function () { + + console.log('system.js/configure-import-meta-url/main.js'); + + } + }; +}); diff --git a/test/form/samples/configure-import-meta-url/_expected/umd.js b/test/form/samples/configure-import-meta-url/_expected/umd.js new file mode 100644 index 00000000000..fb16fd659d9 --- /dev/null +++ b/test/form/samples/configure-import-meta-url/_expected/umd.js @@ -0,0 +1,8 @@ +(function (factory) { + typeof define === 'function' && define.amd ? define(factory) : + factory(); +}(function () { 'use strict'; + + console.log('umd.js/configure-import-meta-url/main.js'); + +})); diff --git a/test/form/samples/configure-import-meta-url/main.js b/test/form/samples/configure-import-meta-url/main.js new file mode 100644 index 00000000000..d9536a69b3f --- /dev/null +++ b/test/form/samples/configure-import-meta-url/main.js @@ -0,0 +1 @@ +console.log(import.meta.url); diff --git a/test/misc/optionList.js b/test/misc/optionList.js index ab34fa25c8c..57b7a6cb097 100644 --- a/test/misc/optionList.js +++ b/test/misc/optionList.js @@ -1,3 +1,3 @@ exports.input = 'acorn, acornInjectPlugins, cache, chunkGroupingSize, context, experimentalCacheExpiry, experimentalOptimizeChunks, experimentalTopLevelAwait, external, inlineDynamicImports, input, manualChunks, moduleContext, onwarn, perf, plugins, preserveModules, preserveSymlinks, shimMissingExports, treeshake, watch'; -exports.flags = 'acorn, acornInjectPlugins, amd, assetFileNames, banner, c, cache, chunkFileNames, chunkGroupingSize, compact, config, context, d, dir, dynamicImportFunction, e, entryFileNames, environment, esModule, experimentalCacheExpiry, experimentalOptimizeChunks, experimentalTopLevelAwait, exports, extend, external, f, file, footer, format, freeze, g, globals, h, i, indent, inlineDynamicImports, input, interop, intro, m, manualChunks, moduleContext, n, name, namespaceToStringTag, noConflict, o, onwarn, outro, paths, perf, plugins, preferConst, preserveModules, preserveSymlinks, shimMissingExports, silent, sourcemap, sourcemapExcludeSources, sourcemapFile, strict, treeshake, v, w, watch'; -exports.output = 'amd, assetFileNames, banner, chunkFileNames, compact, dir, dynamicImportFunction, entryFileNames, esModule, exports, extend, file, footer, format, freeze, globals, indent, interop, intro, name, namespaceToStringTag, noConflict, outro, paths, preferConst, sourcemap, sourcemapExcludeSources, sourcemapFile, sourcemapPathTransform, strict'; +exports.flags = 'acorn, acornInjectPlugins, amd, assetFileNames, banner, c, cache, chunkFileNames, chunkGroupingSize, compact, config, context, d, dir, dynamicImportFunction, e, entryFileNames, environment, esModule, experimentalCacheExpiry, experimentalOptimizeChunks, experimentalTopLevelAwait, exports, extend, external, f, file, footer, format, freeze, g, globals, h, i, importMetaUrl, indent, inlineDynamicImports, input, interop, intro, m, manualChunks, moduleContext, n, name, namespaceToStringTag, noConflict, o, onwarn, outro, paths, perf, plugins, preferConst, preserveModules, preserveSymlinks, shimMissingExports, silent, sourcemap, sourcemapExcludeSources, sourcemapFile, strict, treeshake, v, w, watch'; +exports.output = 'amd, assetFileNames, banner, chunkFileNames, compact, dir, dynamicImportFunction, entryFileNames, esModule, exports, extend, file, footer, format, freeze, globals, importMetaUrl, indent, interop, intro, name, namespaceToStringTag, noConflict, outro, paths, preferConst, sourcemap, sourcemapExcludeSources, sourcemapFile, sourcemapPathTransform, strict';