Unfortunately, there were not the working solution for the question How to setup the TypeScript compiler for the library so that the unused modules will be cut off by Webpack in the dependents projects? (for the Sep. 2021). The solution suggested by Mr. Craig Hicks works only locally and can not be used for the distributable library (I'll explan the details below).
However, from the Mr. Hicks's answer I knew that to make Webpack three-shaking available it's required to distribute the library as ES modules. It makes the issues for usage with Node.js native and ts-node, but I afraid I will be downoved if try to consider all of these problems in single question.
Target
The target library @yamato-daiwa/es-extensions has a lot of functionality and even in big applications a part of it will not be used. Theoretically, the Webpack's three shaking could cut off the unused functionality, but actually it works with huge limitations as it will be shown in experiments below.
In the sample below, I am expecting that only isUndefined
function will be bundled and any other functionality will NOT be:
import { isUndefined } from "@yamato-daiwa/es-extensions"
const test: string | undefined = "ALPHA";
console.log(isUndefined(test));
console.log("End of the script");
Here is the full repository with reproduction consists from the local copy of @yamato-daiwa/[email protected]
(Library directory) and consuming project (ConsumingProject directory).
Experiment 1: Close to real
In this experiment, I'll install the library as usual:
{
/* ... */
"dependencies": {
"@yamato-daiwa/es-extensions": "1.0.1-experimental2"
}
}
For the trial results, I'll remove all dependencies before install them:
npm run "Clear dependencies and reinstall"
where Clear dependencies and reinstall
is:
"scripts": {
"Clear dependencies and reinstall": "(rm node_modules || del node_modules /F /Q) && npm i",
"Webpack:ProductionBuild": "webpack --mode production"
}
Next, I'll run the "Webpack:ProductionBuild"
. In compiled BrowserJS.js
we can see that whole library has been bundled (1 row and 21579 columns for minified version):
(()=>{"use strict";function e(e){return null!==e}function t(e){return void 0!==e}function i(e,t){return void 0===e?t:e}
/* and so on ... */
This experiment available in the "experiment1-close_to_real" branch.
Experiment 2: Get the library locally
Now the ConsumptingProject
refers locally to Library
:
"dependencies": {
"@yamato-daiwa/es-extensions": "../Library"
}
It's important to clean previous node_modules
and reinstall the dependencies:
npm run "Clear dependencies and reinstall"
Then,
npm run "Webpack:ProductionBuild"
The output BrowserJS.js
has exactly 21579
columns as in previous experiment.
This experiment is available in experiment2-local_dependency
branch.
Experiment 3: Getting the library locally from Distributable
directory
Now the library will be got from the Distributable
directory of the Library
:
"dependencies": {
"@yamato-daiwa/es-extensions": "../Library/Distributable"
}
This is what Mr. Hicks suggested.
Let's clean the previous node_modules
and reinstall the dependencies:
npm run "Clear dependencies and reinstall"
And if we execute the "Webpack:ProductionBuild"
, the unused functinality finally will be cut off:
(()=>{"use strict";console.log(!1),console.log("End of the script")})();
But what this solution matters for the published library?
Normally, the library will be installed as @yamato-daiwa/es-extensions
, so what I and library users need three shaking works for this case. By other works, in the Experiment 1 we need same results as in this, third experiment.
This experiment available in "experiment3-local_distributable" branch.
CodePudding user response:
It appears that declaring "sideEffects": false
is the responsibility of each package an application consumes, so setting it in the application's root package.json isn't enough.
The package.json of @yamato-daiwa/es-extensions
needs to include "sideEffects": false
, so applications know that package is side-effect free. I tried this in your first example repo, and the final build gave me the expected:
(()=>{"use strict";console.log(!1),console.log("End of the script")})();