Change: Closer adherence to module specification
Change pattern proposal: Webpack & Node modules to EcmaScript Modules
Old Pattern
Until now, the frontend codebase relies heavily on Webpack and "Node-style" (disk-dependent) import syntax.
New Pattern
The frontend should adhere as closely as possible to the standard module syntax (primarily: relative/absolute paths & extensions).
Advantages of switching patterns
- This is a standardized syntax that every web browser understands implicitly
- Betting on the web has never not paid off!
- There's no ambiguity in imports (the module API we consume as developers!)
- We reduce - or even eliminate - our dependence on compilers and bundlers
- In a world with Dynamic imports, import maps, HTTP/2, and standardized ES modules, browsers can efficiently load only the code we need without any extra tooling
- We more easily unlock access to modern build tooling like esinstall or esbuild (No deploy-time reliance on third party registries! up to 100x faster builds!)
Disadvantages of switching patterns
- Like most of the things I suggest in this repository, this will touch virtually every file - a massive undertaking
- Some people don't like typing extensions?
- One of the beautiful things about the standard syntax is your editor will be able to autocomplete imports 100% of the time!
- Our aliases obscure some pretty gnarly import graphs that would be exposed by using relative paths (an opportunity for flattening and abstraction!)
- Before changing the structure of our codebase, two shortcuts can be used:
- During linting, aliases can be automatically expanded in the source code
- During authoring, aliases can be expanded in the editor
- Before changing the structure of our codebase, two shortcuts can be used:
- Certain things - like
ee_else_ce
are logic-encoded-as-Webpack-syntax. This isn't quite as simple without Webpack, but completely achievable- For example:
// Somewhere in the codebase import { myExport } from "../../../ee_features/module.js"; // earlier... // ee_features/module.js var module = `${ IS_EE ? "/ee/" : "/" }some/feature/name.js`; // I'm fudging the syntax a bit here, I believe you have to await the import on a line separate from the export export * from ( await import( module ) );
What is the impact on our existing codebase?
In terms of lines changed and files touched, it would essentially touch every file, and most of the import
lines (since our linter expressly forbids the standardized extension).
In terms of operation, nothing changes. We just rely less on our bundler and more on the language itself.
However, relying more closely on the standard syntax allows us to move more closely with web specifications, which will enable us to drop unnecessary tooling, adopt modern browser features more readily (e.g. import maps, HTTP/2+, standard library modules, etc.).
While this change won't have a tangible effect now (other than being more standards compliant), it will have an outsized effect in the future as we move beyond the age of Webpack.
Reference implementation
I don't believe this change needs a reference implementation, as it's just "let's stick closer to standardized import syntax."