Like lodash, the library @yamato-daiwa/es-extensions suggests the common functions for both BrowserJS and NodeJS, but unlike lodash it has single main file index.js
with re-exports.
This library:
The conflicting point is the modules type. To make the Webpack's tree shaking available, the ES modules are required, but currently NodeJS supports CommonJS modules only, and in ts-node the ES modules support is limited (especially in the library exporting case).
What we have is:
Modules type | BrowserJS (Webpack) | Tree shaking | NodeJS | ts-node |
---|---|---|---|---|
CommonJS | Yes | No | Yes | Yes |
ES20XX | Yes | Yes | No | Limited |
Because the tree shaking is critical for BroswerJS, it's already been decided to distribute the library by ES2020 modules. But this way, the support for NodeJS and ts-node will be lost.
Even if to build the NodeJS application with Webpack where it's not recommended to bundle the NodeJS libraries (webpack node modules externals is being used to exclude them), application will crush if don't add the @yamato-daiwa/es-extensions
with it's ES modules to excluding of webpack node modules externals.
In this repro, npm run "Webpack:ProductionBuild"
will build the files BrowserJS.js
and NodeJS.js
for appropriate environment. Because the source code using isUndefined
function of "@yamato-daiwa/es-extensions"
library only, in BrowserJS.js
must not be any other functionality (Webpack's tree shaking):
(()=>{"use strict";console.log(!1),console.log("End of the script")})();
Well, it was the cleared challenge. The subject of this question isNodeJS.js
:
(()=>{"use strict";const e=require("@yamato-daiwa/es-extensions");console.log((0,e.isUndefined)("ALPHA")),console.log("End of the script")})();
If we try to run it, we will have the error:
C:\Users\***\WebpackDoesNotCuttOfTheUnusedFunctionality\ConsumingProject\node_modules\@yamato-dai
wa\es-extensions\Distributable\index.js:6
export { default as formatNumberWith4KetaKanji } from "./Numbers/formatNumberWith4KetaKanji";
Now let's try to run it via ts-node (npm run "TSNode test"
):
> ts-node index.ts
(node:18148) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
(Use `node --trace-warnings ...` to show where the warning was created)
C:\Users\***\WebpackDoesNotCuttOfTheUnusedFunctionality\ConsumingProject\index.ts:1
import { isUndefined } from "@yamato-daiwa/es-extensions";
Does in mean "you must change the library"?
This question has been asked before TypeScript 4.5 release. Maybe its new functionality will solve these problems?
The "main"
entry in a package.json
file should always be in commonjs format. The "module"
entry should always be es modules. Right now, you have "main"
pointing to es modules, which will not be resolved properly (your ts-node
error, for example).
Generally, if you want to give consumers the option, you would create 2 builds in the distributable.
(you'll need to remove the comments in these json files)
// tsconfig-esm.json
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "ES2020",
// es module build target
"outDir": "Distributable/esm"
}
}
// tsconfig-cjs.json
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "commonjs",
// commonjs build target
"outDir": "Distributable/cjs",
// the other one will build types, so not needed here
"declaration": false
}
}
Then, in your package.json
:
"main": "./Distributable/cjs/index.js",
"module": "./Distributable/esm/index.js",
"types": "./Distributable/esm/index.d.ts",
"scripts": {
"build": "rimraf Distributable && tsc -p tsconfig-cjs.json && tsc -p tsconfig-esm.json",
"Lint": "eslint Source Tests"
},
"files": [
"Distributable"
],
"devDependencies": {
"rimraf": "^3.0.2",
Note:
build
is idiomatic. The spaces would drive me nuts, as npm run Rebuild distributable
wouldn't work. You have to either quote like npm run 'Rebuild distributable'
or escape like npm run Rebuild\ distributable
"files"
entry in package.json
, you no longer need .npmignore
. This means "package only the files specified", which is much safer than having to remember to add every new file to an ignore list.rimraf
dependency, which is a common tool for deleting the dist directory in a platform-independent way. del-cli
only works for windows.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With