A dependency package that I'm using only has module and main as entry points. By default, the webpack version I'm using resolves to module entry point first. If I set resolve.mainFields to main in webpack configuration, I might affect other dependencies that were being resolved by 'browser' entry point by default.
So, the question is, how can I transpile a dependency like that and have it bundled in my bundle in ES5?
Some package writers distributes their ES6 sources, some other don't.
If you can figure out what "modern JavaScript syntax" the dependency is using, In general, the standard format for distributing a module is called CJS or Common JS.
If the author of the package you are trying to use did not export CJS from it's bundle (in 99% they do), then you don't need to transpile anything.
What do you mean by "the other ones"?
Be sure to import the right sources.
Related
In the documentation for Node's native support of ECMAScript modules, they state
There are three types of specifiers:
...
Bare specifiers like 'some-package' or 'some-package/shuffle'. They can refer to the main entry point of a package by the package name, or a specific feature module within a package prefixed by the package name as per the examples respectively. Including the file extension is only necessary for packages without an "exports" field.
...
The definition of bare specifiers indicate you can import ECMAScript Modules from "packages".
What's considered a "package" in Node.js? Does node just search the entire node_modules folder for any folder with a package.json file and consider that a package? Or is it more complicated than that? Is it the same for CommonJS modules and ESMAScript modules?
What's considered a "package" in Node.js?
In the sense of "bare" named packages for ESM, any name that matches a node builtin package, or is in node_modules/{{ bare name }} in the current directory or subsequently any parent directory, that has a package.json that loads and also has the correct name field.
Does node just search the entire node_modules folder for any folder with a package.json file and consider that a package? Or is it more complicated than that?
Basically, node doesn't care about anything you haven't named as an import though. It's always more complicated, the algorithm is documented further down on the ESM modules page.
Is it the same for CommonJS modules and ESMAScript modules?
No, although the part that resolves the package exports is shared once a "package" is located and vetted by the ESM or CommonJS rules). Big differences are
Global node_modules are not considered in ESM (i.e. traversing $NODE_PATH, $HOME and the node $PREFIX).
Outside of the process for loading this subset or "bare names" there are more differences.
ESM modules or mjs files will not load via require.
No native or JSON imports
Generally the ESM loader is a much more strict subset of CommonJS as anything Node specific doesn't apply.
I'm curious how tree-shaking/dead code elimination of ESM works. I'm using Typescript for various Node.js projects and I started to export my own ESM packages (tsc --module es2015 --target es5 --outDir dist/esm) instead of CJS packages. Moreover, I tried to replace dependencies (like lodash) that are only available as CJS module with libraries that are available as ESM.
When I build a project, my entire TS codebase (./src) is transpiled to JS (./dist); dependencies are still taken from (./node_modules). No tree-shaking performed.
I guess I'd still need a bundler (like Webpack) that needs (at least) an entry point so that it can shake away everything that's not needed, so that I can reduce the package size of (e.g.) an AWS lambda? Is this something you would do?
When you use import instead of require, the transpiler is able to build the dependency tree on compile time (that is why you cannot dynamically import code).
For example, if you write this:
import { myfunc } from 'mylib';
The transpiler understands that you only need the myfunc function from mylib. If mylib includes other functions that are not used by myfunc, the transpiler can remove them from the bundle.
This is the short version. Tree-shaking is actually more complex than that. Webpack has a good article about it if you want to learn more:
https://webpack.js.org/guides/tree-shaking/
I'm approaching modules for the very first time and I'm a little bit confused.
I read from various docs that there are several modules systems, like commonjs (sync), and requirejs (AMD). From ES6 plain javascript has its own module sys, which is based on commonjs.
Then I started studying webpack, that resolves dependency using commonjs or requirejs module formats, and from here starts my confusion: as far as I understand, those two are module systems, they are designed to resolve the dependencies tree on its own; it's their purpose.
What is the sense to use the commonjs/requirejs format (aka syntax) and then implement webpack to resolve the graph?
CommonJS and AMD are both runtime module systems. Webpack is compiling your code, so you're not using it to resolve the graph specifically, you're using to create a build of an application from source files. To accomplish that, webpack 'understands' both types of modules so that it can analyze your code, identify dependencies, and bundle and optimize appropriately.
Webpack supports things that the original module systems don't: you can use more dynamic expressions to represent the module you're requiring; you can extend the require resolution behavior itself; you can specify an asynchronous runtime loading using its require.ensure syntax. Webpack's author could have defined a new module system to support these additional features, but then you'd have to rewrite all your existing source (and any third party modules) to accommodate the build tool. Instead, webpack is good about supporting whatever modules you already use, and giving you additional tools to handle more complex build needs.
I'm using jspm and SystemJS to import ES2015 modules.
Is it possible to get a list of all of the imported modules in a project through the System object, or anywhere else? I can access my project-specific modules through System._loader.moduleRecords, but the modules that I've installed through jspm (e.g., d3, jquery) do not appear in this list.
System._loader.modules contains a list of all modules, but unfortunately also includes a list of modules required to transpile my code and modules-loading packages.
System._loader.moduleRecords (project modules)
System._loader.modules (project modules, libraries, transpile packages)
I want only a list of declared imports, specifically, those that I've imported using import x from 'x'. This should include both project modules and libraries, but not babel/module-loading related modules. I'd like the solution to not involve filtering using regular expressions.
SystemJS Debugger is probably what you are looking for.
I use requirejs and typescript for a node_module.
https://github.com/Ayolan/validator-extended/blob/master/app.js
It works but I cannot load it once installed from npm.
It looks like the requirejs config on the node_module change the config of my project (baseUrl and nodeRequire config actually).
There is a way to use TS and requirejs on a node_module?
Node.js does not use the AMD specification for JavaScript modules but instead the CommonJS modules. You'll need to tell the TypeScript compiler to compile your modules to this specification. This can be easily achieved by passing in the --module "commonjs"flag to the compiler.
Please note, that although the CommonJS spec uses the require keyword, this is something completely different than RequireJS. Node.js does not rely on RequireJS for it's module loading, it has its own module loader that is based on the CommonJS spec.
In short: try to avoid using RequireJS and node.js.
His question makes sense. Using requirejs in node has a number of advantages over the standard commonjs: http://requirejs.org/docs/node.html
How to build node modules with AMD / Requirejs:
http://requirejs.org/docs/node.html#nodeModules
If you don't need requirejs AND node at the same time
That was my case when I had 2 separated typescript builds, one for the front and one for the back but I had only one package.json to put all the "#types" in so tsc would pick both .d.ts in node_modules/#types
You can just manually tell tscto take certain types with the type option:
types: [ "requirejs" ] for the front and types: [ "node" ] for the back
Hope this helps.