Moving to TypeScript entails configuring how the JavaScript will be eventually consumed by both the server and the client.
Separating the Client Bundle from the Server Bundle
The server code runs in Node while the client code runs in the
browser. advises separating the
configurations for advantages like faster type-checking and compiling,
lower memory usage when using an editor, and improved enforcement of the
logical groupings of your program.
Webpack utilizes loaders to preprocess files, allowing the dev to bundle
any static resource. For example, markdown-loader compiles markdown
into HTML. I’ve been using
ts-loader
, and it should be
informative to know what else is out there, e.g.,
esbuild-loader
,
which has been mentioned at work. esbuild-loader’s claim to fame is
speed; other benefits include transpiling to ES6+ using esbuild.
ts-loader admits to being slow, but because of type-checking all files
in every rebuild though granted that can be dangerously disabled via
transpileOnly: true.
esbuild
makes
bold claims about being pretty fast, e.g., 87x faster than rollup 4 + terser.
ES Modules vs. CommonJS
If package.json omits a value for type, .js files are treated as
if the package.json specified "type": "commonjs". To override the
package.json type value for a given file, use either .mjs for
module treatment or .cjs for CommonJS treatment. On the client side, it seems using ESM is an easy choice given that
we want to use esbuild-loader. The server-side is a bit more
complicated; we have CommonJS working and the attempt at ESM ended up
with challenges similar to those of . Shelving
ESM on the server to a later iteration of the app.
Some libraries do ship ESM variants, i.e., instead of const foo = require('./foo'), you’d have import foo from 'foo/dist/foo.mjs'. Some
library authors respond to demand for ESM. Some popular libraries have
ESM forks, e.g., @esm-bundle and @bundled-es-modules have
collections of such forks.
Build Recipe for Deployment
On the server-side, we need to (1) transpile the TS into JS, so that we
can do node dist/server.js. However, static resources like EJS
templates are not covered by the transpilation step, and thus we need to
(2) copy them over to dist/.
On the client side, we need to (3) transpile the TS into JS. Because the
JS is to be ran in a browser environment, we also need to (4) bundle it
for the web. Lastly, we need to (5) provide the static resources to
where the server will look for them. The current state of things is:
1:tsc, 2:webpack, 3:tsc, and 4,5:webpack.
References
- TypeScript: Documentation - Project References. www.typescriptlang.org . Accessed Apr 20, 2024.
- Loaders | webpack. webpack.js.org . Accessed Apr 21, 2024.
- Modules: Packages | Node.js v22.0.0 Documentation. nodejs.org . Accessed Apr 29, 2024.
- ESM not gaining traction in back-end Node? : node. www.reddit.com . Accessed Apr 29, 2024.
- Going Buildless: ES Modules: Modern Web. modern-web.dev . Accessed Jun 22, 2024.