Reputation: 691
I am currently working on a project where there will be many packages for npm. I want to take a more radical approach on this project. So, no files should be pre-compiled anymore. In the src folders of the packages there will be just only d.ts, ts, js, mjs files (as i said, no one of them should be precompiled anymore). I do this out of laziness and because I think that the time is ready to stop pre-compiling files!
I mean how many variations should I create? ESModules, AMD, CommonJs, SystemJS?
My simple thought is: leave it as it is (import x from 'x', export foo = 123) and the developer that using the package will already have the right tool (Babel, Typescript)! or not?
The second question is: up to which level should the package be compiled down? ES3, ES6? What do package users who only use modern browsers and only support them? Would differential loading be the right approach here? I have only seen differential loading in the environment of HTML files. So as a starting point! This is not the case for me if the packages are used selectively by developers.
Specifically, my question is: do we still have to make all this effort? What is currently the lowest common denominator? I don't know the statistical numbers, but I have the feeling that everybody uses a compiler / preprocessor (Babel, PostCss) in his project?
What do you think about this?
Upvotes: 1
Views: 1752
Reputation: 130491
It depends who is your audience and what tech to they use. For example, you might be using language-related code which Node v19
supports but not Node v12
, and then obviously your code will break their app, once integrated.
What is currently the lowest common denominator?
By pre-transpiling, you can also pre-select the lowest-supported platform (easily by defining browserslist
) and guarantee no code-breaks when anything unsupported will be polyfilled (by core-js
) or transpiled (by Babel or whichever).
Nobody cam really answer "what is currently the lowest common denominator" for you, because it's specific to your product & business. Some apps can decide for their uses the minimum requirements, and some don't have that luxury (are installed by many thousands/millions).
"How many variation to make" - I would say only es
& commonsjs
(as of current times), so some users could benefit from using the es
(still transpiled) code, with imports/exports
, and eventually, hopefully, the usage of commonjs will fade completely (maybe ~5 years from "now", 2023).
Upvotes: 0
Reputation: 13117
From my experience, CommonJS and ES modules are the relevant technologies these days. You might decide to skip CommonJS, then you would get along without transpilation. However, many frameworks and other libraries still rely on CommonJS, and they cannot use ES modules.
What you could do, as a lightweight approach, is the following:
First: Write everything as ES modules by default, and lay out your package to be used as ES module(s) by default (e.g. set "type":"module"
in your package.json and use .mjs
as file ending).
Then: Use Babel, but only to create a CommonJS fallback of your modules. This could look like this:
Add the following dev dependencies to your project. (There are other Babel plugins for special cases of syntax; Babel will usually tell you which ones it needs):
npm install --save-dev @babel/cli @babel/core @babel/plugin-syntax-import-meta @babel/plugin-transform-modules-commonjs
Then add the following block to your package.json:
"babel": {
"plugins": [
[ "@babel/plugin-transform-modules-commonjs" ],
[ "@babel/plugin-syntax-import-meta" ]
]
}
Now you can transpile your ES modules to CommonJS with a simple line of shell code:
# assuming your ES modules are in the lib/ directory
for script in $(find lib/ -iname '*.mjs' | grep -v test.mjs | sed -e 's|.mjs||g'); do
npx babel $script.mjs > $script.cjs
done
You can also add this as a script to your package.json.
"scripts": {
"build": "for script in $(find lib/ -iname '*.mjs' | grep -v test.mjs | sed -e 's|.mjs||g'); do npx babel $script.mjs > $script.cjs; done"
}
Now you can run this with npm run build
, add it as a commit hook, or run it before pushing to the NPM registry. You could also built to a different folder than where your ES modules live, and exclude that folder via .gitignore.
This is how I created several libraries of mine (for the exact same reasons), and it works perfectly – both in CommonJS and in ES module environments.
By the way, NodeJS has some documentation on shipping packages as both ES modules and CommonJS: https://nodejs.org/api/esm.html#esm_dual_commonjs_es_module_packages
Upvotes: 2