I'm using Typescript, ES6 module syntax, and SystemJS / builder.
The basic requirements I'm trying to do are:
import * as _ from 'lodash'
)The config I'm using for the build and dev / production env just to get it up and going:
System.config({
meta: {
"lodash": {
"format": "global",
"build": false,
"exports": "_"
}
// ...more meta
},
map: {
"lodash": "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.min.js",
// ...more maps
}
});
From here I have a npm task which transpiles to ES6 and then bundles everything into a single file through babel plugin. The script is loaded directly on the production page fine and it loads. The issue is once a global dependency imports I keep getting errors like "_.clone is not a function" etc due to systemjs wrapping the CDN imports with an object like
{default: _ } //_ is the actual lodash export
I've been successful in changing the import to import _ from 'lodash'
but then I get IDE errors since lodash (nor any other global script like angular) does not export a default value and I lose code completion.
What's the correct way to meet the requirements with systemjs / builder here?
As a side note I'm fine with using script tag loading instead of systemjs CDN imports if that works better.
TypeScript has a flag --allowSyntheticDefaultImports
for just this scenario. Specifically, it informs the typechecker that another transpiler, loader, or bundler provides maps module.exports
to exports.default
in a later step.
You can specify this flag in under compiler options in tsconfig.json
{
"compilerOptions": {
"target": "esnext",
"module": "es2015",
"allowSyntheticDefaultImports": true,
"moduleResolution": "node",
"baseUrl": "."
}
Note that when the module format is set to "system"
, this flag is set implicitly.
Now you can write
import _ from "lodash";
and TypeScript will understand it, typecheck it, and validate that it is used correctly. However, this only affects typechecking. You still need, and in this case already have, a loader or intermediate transpiler that provides the runtime synthesis.
import * as _ from "lodash";
violates the proposed NodeJS -> ESM interop proposal and, if you call it as in _([1, 2]).map(x => x ** 2)
also violates the ES spec which forbids a Module Namespace Object from being callable., so you are doing well to take advantage of the --allowSyntheticDefaultImports
flag and the interop provided by SystemJS.