Constructing a modern 2023+ JS build pipeline.
npm installDevelop in src/ using React, TypeScript and PostCSS with nesting and mixins. Use VSCode integrations for Prettier, ESLint, and Stylelint to add author-time formatting and hints.
Start the app in local development mode.
Build the application into deployable assets. Lints, typechecks, and tests must pass to build.
Enforce a consistent style and quality level in JavaScript with ESLint.
Enforce a consistent style and quality level in CSS with Stylelint.
Run local tests with Vitest
Generate an interactive visualization of the bundle composition and size using rollup-plugin-visualizer.
An ongoing list of projects tested and what I'm learning about them.
- Vite is a lot closer to Webpack than I thought it would be. Plenty of magic going on under the hood, a decent sized ecosystem of plugins.
- A main goal with this repo will be to output the most modern built files possible, avoiding transpilation of any 2020+ browser acceptable code. Preferably ES module imports, dynamic imports, native async/await, etc.
- Vite uses rollup and rollup plugins under the hood! Finally my boy rollup in the spotlight ๐๐ผ.
- Vite manages the root-level index.html, just like Webpack. This file is used for dev serving, and it's altered and copied to
dist/when runningbuild. - Vite and EsBuild prefer to use the
.jsxextension to apply jsx transforms. We're using.tsxfiles here, but worth noting that the ~2017+ best practice of calling all files JS, whether they have JSX in them or not, is now outdated.
- Looks like the Vite config exposes most of the ESBuild transpilation and compilation options, including target browser support!
- Vite handles SWC internally, without settings exposed. SWC's default behavior is to target ES5 (awful for performance), but from what I gather from the react-swc plugin source, Vite configures SWC to target ES2020.
- The React-swc plugin only "Replaces Babel with SWC during development". "During builds, SWC+esbuild are used when using plugins, and esbuild only otherwise". I prefer to minimize the number of tools doing a single job to make config and debugging easier, so ESBuild seems like a better choice with Vite. Some tweets from Evan point to SWC being the eventual default, but only for very large projects (1000s or 10000s of files).
- ESBuild with Jest is much less mature. I hacked it together but ran into some issues with css modules and RTL user event imports that required workarounds. Might contrib to
jest-esbuild-transformto get plugins (css modules) working for Jest transforms Edit: After further exploration, it's not immediately solvable. Documentation around create-a-transformer are also light / lacking. I'm going to sidestep the issue by switching to the Vite-centric Vitest.
- Note that with Vite, we run
tscwithno-emitfor author and compile time type checking, and use EsBuild to transpile the TS into JavaScript. - In order to use TS for config files, we need to configure the CLI and the editor (VS Code) to use an executor that understands TS without compilation (i.e., ts-node). That's one step too far for me right now, so config files will remain in JS.
- Vite is using PostCSS for
@imports by default. We have access to a PostCSS config to add autoprefixing and some additional niceties like nesting and mixins. - No need for other CSS precompiler features (variables or functions). Modern CSS is the ๐'s ๐ฆต๐ผ.
- Vite handles CSS url/import resolution.
- Advanced functionality: Looks like the
?inlineloader/query param doesn't work with Vite'sNodeNextimports enabled. See this guide for more info on code splitting: https://vitejs.dev/guide/features.html#css-code-splitting. EDIT: This has become a moot point as I've had to revert to vitenodeimports to support npm module*.d.tsresolution.
- There's a new test runner native to node, but I don't think it's ready for wide usage. The ecosystem is thin, and the failed test output is not as descriptive as other options.
- Ava is focused on node and functional ES code; Jest and related are a better fit for a mix of node and DOM testing.
- Jest: the first package that comes up when you search Jest and ESBuild is abandoned, but there's a very light Jest transformer wrapper at https://github.com/AkifumiSato/esbuild-jest-transform. ESBuild options are pass through and ESBuild is a peer dependency. Ideal!
- BUT, due to Jest usually running transformers in sync mode, we can't use plugins like css-modules in esbuild-jest-transform. I hacked at esbuild-jest-transform for a bit, but wasn't able to trigger an
asyncProcesstransform. I think it might have to do with how Jest chooses whether a .js file is an ES or common-style module. References: AkifumiSato/esbuild-jest-transform#7, https://jestjs.io/docs/code-transformation, evanw/esbuild#2821, https://github.com/kulshekhar/ts-jest/blob/main/src/legacy/ts-jest-transformer.ts - Vitest looks interesting โ it's got the great benefit of using Vite build/plugins in the exact same configuration as production builds. It's young and doesn't seem as focused or clearly documented as Jest, but it's worth trying just for the consistency of code transformations. Edit: Adding it was pleasant! Let's do it!
- Is there any alternative? At this time I don't think so.
- https://browserslist.dev/ is a nice little resource for visualizing browserslist query results.
- Big thanks to Mehdi M. for writing this very clear article on getting browserslist and EsBuild working together.
- Rollup has a bundle analyzer too! It's less pretty than webpack's, but still very nice to have around.