-
Notifications
You must be signed in to change notification settings - Fork 11.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Make moment optional from our UMD builds
Create a rollup plugin altering the UMD header to wrap optional dependencies between try/catch, which allows to load moment only when the dependency is installed. Since AMD loaders are asynchronous, `'moment'` needs to be explicitly loaded before 'chart.js' so when 'chart.js' requires moment, it's already loaded and returns synchronously (at least with requirejs).
- Loading branch information
1 parent
8a3eb85
commit 29e54d8
Showing
2 changed files
with
69 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/* eslint-env es6 */ | ||
|
||
const UMD_WRAPPER_RE = /(\(function \(global, factory\) \{)((?:\s.*?)*)(\}\(this,)/; | ||
const CJS_FACTORY_RE = /(module.exports = )(factory\(.*?\))( :)/; | ||
const AMD_FACTORY_RE = /(define\()(.*?, factory)(\) :)/; | ||
|
||
function optional(config = {}) { | ||
return { | ||
name: 'optional', | ||
renderChunk(code, chunk, options) { | ||
if (options.format !== 'umd') { | ||
this.error('only UMD format is currently supported'); | ||
} | ||
|
||
const wrapper = UMD_WRAPPER_RE.exec(code); | ||
const include = config.include; | ||
if (!wrapper) { | ||
this.error('failed to parse the UMD wrapper'); | ||
} | ||
|
||
let content = wrapper[2]; | ||
let factory = (CJS_FACTORY_RE.exec(content) || [])[2]; | ||
let updated = false; | ||
|
||
for (let lib of chunk.imports) { | ||
if (!include || include.indexOf(lib) !== -1) { | ||
const regex = new RegExp(`require\\('${lib}'\\)`); | ||
if (!regex.test(factory)) { | ||
this.error(`failed to parse the CJS require for ${lib}`); | ||
} | ||
|
||
// We need to write inline try / catch with explicit require | ||
// in order to enable statical extraction of dependencies: | ||
// try { return require('moment'); } catch(e) {} | ||
const loader = `function() { try { return require('${lib}'); } catch(e) { } }()`; | ||
factory = factory.replace(regex, loader); | ||
updated = true; | ||
} | ||
} | ||
|
||
if (!updated) { | ||
return; | ||
} | ||
|
||
// Replace the CJS factory by our updated one. | ||
content = content.replace(CJS_FACTORY_RE, `$1${factory}$3`); | ||
|
||
// Replace the AMD factory by our updated one: we need to use the | ||
// following AMD form in order to be able to try/catch require: | ||
// define(['require'], function(require) { ... require(...); ... }) | ||
// https://github.com/amdjs/amdjs-api/wiki/AMD#using-require-and-exports | ||
content = content.replace(AMD_FACTORY_RE, `$1['require'], function(require) { return ${factory}; }$3`); | ||
|
||
return code.replace(UMD_WRAPPER_RE, `$1${content}$3`); | ||
} | ||
}; | ||
} | ||
|
||
module.exports = { | ||
optional | ||
}; |