Page MenuHomePhabricator

Determine how the shared component library will be built and distributed
Closed, ResolvedPublic

Description

Summary

Decision around build tools (Webpack, Rollup, Vite, etc), formats (CommonJS, ESModules, UMD), delivery (vendored in MediaWiki? Published to NPM?), etc.

Considerations

Build tool
  • Main options are probably Webpack, Rollup, Vite, or potentially ESBuild on its own
  • Tools and dependencies may need to be audited by security; this may also require upgrading Node version in our CI stack; does this block us from using tools we want outside of MW infrastructure (Github or Gitlab CI, for example) if we need support immediately?
  • Webpack
    • Webpack has been the de-facto standard for a long time, but it is also very complex and pretty resource-intensive.
    • Webpack has been criticized for having a very large number of dependencies, and a lax approach to dependency management
    • Webpack seems to be the only build tool that can easily output code into "CommonJS2" format (as opposed to plain CommonJS format). CJS2 is directly compatible with ResourceLoader's own module system; minor additional work is needed to support plain CJS (see T284511).
  • Vite/Rollup
    • Tools like Rollup or Vite (which is based on Rollup) make it easy to do tree-shaking (dead code elimination)
    • Rollup and Vite are much faster than Webpack, and have fewer dependencies
    • A proof of concept exists for integrating Vite's hot module reloading feature into MediaWiki (see T277747#7084241)
    • Vite requires Node.js v12 or higher, while WVUI's CI currently uses Node.js v10 (see T284253)
    • Wikidata Query Builder was recently migrated to Vite
  • Storybook used to require Webpack, but it recently added support for alternate builders like Vite
Other development tools
  • What else should we incorporate into the shared library? Beyond standard things like linters and tests, this would include things like Storybook
  • Potential Storybook improvements:
Bundling
  • WVUI's current approach of bundling specific builds for different use-cases upstream, as part of the library (full build vs search build for example) is not sustainable as a general strategy in the long run; by providing an ESModule build of our shared library and allowing consuming applications to use their own build tools, each consumer could bundle only the needed components
  • What kinds of bundles do we want to actually ship?
    • Supported formats (CommonJS, ESModules, etc)
    • Application-specific builds (like WVUI search, etc)
    • How does CSS get bundled? How can (the equivalent of) tree shaking for CSS be supported?
Delivery
  • How should the library be included in MediaWiki? Alternatives include:
    • "Vendored" in resources/lib/, automated with foreign-resources.yaml. This treats it as an external library, only updating it when a new release is published. (This is how OOUI is managed.)
    • As a git submodule in MediaWiki. Updates could be manual or automatic (through Gerrit), and would be more frequent than published releases.
    • Each feature/module that needs it uses a build step to tree-shake just the parts of the library it needs. There's no centralized copy of the library in MediaWiki, each build step independently gets it from NPM.
  • How should MediaWiki provide the library? Alternatives include:
    • Provide the entire library as a ResourceLoader module. Less efficient on pages with only one feature because unused code is loaded, but possibly more efficient on pages with multiple features, because there's no double-loading.
    • Make individual users of the library tree-shake the parts they need using a build step. This doesn't load any unused code, but could double-load code on pages where multiple features use the library.
    • Provide individual components or groups of components as separate ResourceLoader modules. This could straddle the unused code / double loading trade-off if done right.
    • Provide both a ResourceLoader option and a build step option, and decide which to use on a case-by-case basis. A feature that only loads on a special page might choose to use a build step, while a feature that could load in many different environments might choose to use the RL module. This could allow for more optimization, but could also result in even more double-loading.
  • How should MediaWiki provide icons from the library?
    • For icons, the trade-off is different and weighs more heavily in favor of having each module embed the icons it needs, thereby avoiding loading (lots of) unused icons rather than trying to avoid double loading; see parts of T282625#7080454 and T282625#7083670 for some discussion of this
    • A build step with tree shaking could do this embedding. As an alternative for code that doesn't use a build step, we could provide a ResourceLoader directive that embeds a specified set of icons in a module. This would be easy to do as long as the library makes the full set of icons available as a JSON file.
    • If there is code that gets the components from a ResourceLoader module but tree-shakes the icons through a build step, that code will need to be able to import the components and icons separately, and its build step will need to know to externalize the components but inline the icons. For this reason we may want to publish the components and the icons as separate NPM packages.

Questions

1. Which build tool will we use to generate a production version of the shared library?

Design Systems Team proposal: Use Vite. Convert WVUI from Webpack to Vite once CI upgrades to Node 12.

2. What other development tools do we want to incorporate into the shared library?
3. What kinds of bundles do we want to actually ship?

Design Systems Team proposal: Provide separate builds of the component library and the icon set (perhaps publish them as separate NPM packages). Publish both in ESModule format and CommonJS format. Maybe keep an application-specific build for search until the Vector search can use a build step, but don't provide any other partial or application-specific builds.

4. How to deliver the shared library?

Design Systems Team proposal: Vendor the library in MediaWiki. Provide the components as a single ResourceLoader module, but consider splitting it up later if the need arises. For icons, encourage use of either a build step to tree-shake only the icons needed, or a ResourceLoader directive to embed specified icons.


Decisions

The new shared library will be built using Vite. We will provide various bundles to support different use-cases (ES Modules, CommonJS, and browser script tag). An ES5 legacy bundle will not be provided (library will be in Vue 3 which requires ES6). We will continue using Storybook as a development tool.

We will continue to vendor a bundle of this shared library in MediaWiki. The future work around a front-end build step will also impact how developers consume this library in their own projects.

Event Timeline

egardner updated the task description. (Show Details)
egardner updated the task description. (Show Details)
egardner updated the task description. (Show Details)