Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setup toolchain & build system #10

Open
16 of 20 tasks
olange opened this issue Jan 14, 2021 · 6 comments
Open
16 of 20 tasks

Setup toolchain & build system #10

olange opened this issue Jan 14, 2021 · 6 comments
Assignees
Labels
tooling Toolchain and infrastructure

Comments

@olange
Copy link
Owner

olange commented Jan 14, 2021

Desired features

  • Target native JS module system first (ESM)
  • Ability to easily integrate CJS & AMD modules
  • Support for module assets (relative paths in modules & web components)
  • Support for source maps
  • Support for monorepo layout (many artefacts / packages in one repository)
  • Instant startup & Hot-module replacement & fast refresh
  • Unbundled/independent package deployment
  • Clear separation of build pipeline and dev server
  • Reasonably good feedback about errors and outcome of the build pipeline
  • Optimizations such as bundling, treeshaking, minification for a late stage (production build)

Actions

Reference articles

See also

@olange olange changed the title Setup toolchain & build system Toolchain & build system Jan 14, 2021
@olange olange added the tooling Toolchain and infrastructure label Jan 14, 2021
@olange olange changed the title Toolchain & build system Setup toolchain & build system Jan 14, 2021
@olange olange self-assigned this Jan 26, 2021
@olange
Copy link
Owner Author

olange commented Jan 26, 2021

About the choice of Snowpack

  • Coming from the Web Components scene, I though first about bringing in the Modern Web Dev Server, which comes with many desirable built-in integrations & tools, such as, Service workers to preload WebComponent definitions, or the opinionated Storybook build (which is usually based on Webpack); however, its crisp and clever integration of the various parts brought a many questions from newcomers, about the various parts themselves, so I decided to go to a bit less of tooling to start with; however it is constant source of inspiration
  • Snowpack 3 with esbuild offers super-fast start times, good feedback about what are the outcomes of the build pipeline, the initial configuration is rather simple and the optimizations under development will make it easy to add these features later on, if needed; also there are many examples in the wild and its clear separation of the build pipeline and dev server in the documentation make it easier to explain to newcomers
  • Vite.js is functionally on-par with Snowpack and actually pioneered features like Hot-module replacement; it offers excellent documentation on many of the underlying transforms of those build tools and its documentation is another source of inspiration when I look for something.

Why no Rollup in the preliminar study?

  • Before Snowpack, we started with Rollup only but we had a horrible developer experience with its dev server, as it offers no Hot-module refresh: every change & save goes thru the bundling stage, resulting in >2sec. refresh cycle; also, its watcher did not pickup updates to nested Web Components.
  • Rollup builds remain easy to integrate with Snowpack, if needed; as well as using some of Rollup plugins; but we won't make use of them, because Snowpack 3 will bring us all desired optimizations as configuration options; and Snowpack with esbuild is much faster as Rollup.

Service Workers integration

  • Modern Web Dev Server is the one offering the best built-in integration of Service Workers and Web Components with the build pipeline, which is a feature I expect we'll need for the kiosk mode of the embedded webapp
  • Integration of Workbox or hand-written Service Workers is however no fundamental issue with Snowpack (or Vite), so there is no reason to dismiss them for that particular reason
  • We'll actually leave that requirement out for now, it raised many (interesting) questions, not that easy to explain — difference with the browser cache? difference with preloading? when is what going to be cached and serviced from the SW? —; we'll go with the <link rel=preload …> techniques for now.

@olange
Copy link
Owner Author

olange commented Jan 26, 2021

Setting up Babel plugins: decorators and class properties

babel.config.json

{
  "plugins": [
    ["@babel/plugin-proposal-decorators", { "decoratorsBeforeExport": true }],
    ["@babel/plugin-proposal-class-properties", { "loose": true }]
  ]
}

snowpack.config.js

module.exports = {
  
  plugins: [ '@snowpack/plugin-babel' ],};

package.json

{
  
  "devDependencies": {
    "@babel/plugin-proposal-class-properties": "7.12.1",
    "@babel/plugin-proposal-decorators": "7.12.12",},
  
}

About the plugin configuration options

  • @babel/plugin-proposal-class-properties › option loose: when true, class properties are compiled to use an assignment expression instead of Object.defineProperty, which is slower; for an explanation of the consequences of using either, see Definition vs. Assignment (TL;DR in Part 5)
  • @babel/plugin-proposal-decorators › option decoratorsBeforeExport: an option that was added to help TC39 collect feedback from the community by allowing experimentation with both possible syntaxes: export @decorator class Bar {} (decoratorsBeforeExport: false) vs @decorator ␤ export class Foo {} (decoratorsBeforeExport: true)

Reference articles

olange added a commit that referenced this issue Jan 26, 2021
which has out-of-the-box support for ES Modules
with no warning anymore
@olange
Copy link
Owner Author

olange commented Jan 26, 2021

About our Snowpack setup

webapp/snowpack.config.js

// Snowpack Configuration File
module.exports = {
  mount: {
    static: { url: "/", static: true },
    // components: { url: "/components" }
  },
  plugins: [ '@snowpack/plugin-babel' ],
  packageOptions: { },
  devOptions: { output: "stream" },
  buildOptions: { out: "build", sourcemap: true },
  optimize: { }
};

Features

  • Mounts
    • When running Snowpack's dev server: mount static HTML files and assets of the static/ subfolder at root URL /; handle/transform the source files of the components/ subfolder and mount them at the /components URL; the static HTML files can reference those source files with import … from components/module.js
    • When running Snowpack's build pipeline: the static HTML files and assets of the static/ subfolder will be placed at the root of the build/ subfolder; and the source files of the components/ subfolder will be built for production, that is, optimized/bundled/minified/treeshaken/etc., and placed in the build/_snowpack/ subfolder;
    • The output build/ subfolder will be used as the source of Firebase Hosting's deployment; it is therefore linked to Firebase's configuration (firebase.json).
  • Source map support: enabled with sourcemap: true in buildOptions
  • Output in stream mode: enabled with output: "stream" in devOptions, as Snowpack might be run in parallel with other commands from the parent package start scripts
  • Babel plugin for decorators and class properties: see comment hereabove

Reference articles

olange added a commit that referenced this issue Jan 26, 2021
within Snowpack configuration (webapp/snowpack.config.js) as the
deployment to Firebase Hosting depends upon it (firebase.json).
@olange
Copy link
Owner Author

olange commented Jan 26, 2021

About the integration of Firebase with Snowpack

Principles

  • For now, Firebase only hosts the public website (at darcade.app and d-arcade.web.app), which only serves static assets (thru its CDN); we don't use the Firebase Functions or Firestore.
  • Firebase's toolchain is responsible for deploying the static assets, which we configured to take from the webapp/build/ subfolder; and it can be used to preview the statically built webapp, from the same subfolder.
  • Snowpack is reponsible for providing the dev server with hot-module refresh; as well as building the webapp for production.

firebase.json

  • The hosting.public: "webapp/build" setting of Firebase states the same folder as the buildOptions.out: "build" option of Snowpack (in webapp/snowpack.config.js hereafter)
  • The hosting.predeploy: "nom run build:webapp ensures that we have a fresh & clean production build, before deploying to Firebase Hosting.
{
  "hosting": {
    "public": "webapp/build",
    "predeploy": "npm run build:webapp",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ]
  }
}

package.json

  • The deploy script deploys the static assets of the webapp/build/ subfolder to Firebase Hosting (defined in firebase.json hereabove);
  • Before deploying, the build:webapp script will be run (idem);
  • The start:firebase script can be used to preview the static production built that would be deployed with the static dev server of Firebase.
  • The start:webapp and build:webapp rely on Snowpack.
{
  
  "scripts": {
    ,
    "start": "run-p start:webapp",
    "start:webapp": "npm --prefix webapp run start",
    "start:firebase": "firebase serve --only hosting",
    "build": "run-s build:*",
    "build:webapp": "npm --prefix webapp run build",
    "deploy": "firebase deploy --only hosting"
  },
  
}

webapp/snowpack.config.js

The buildOptions.out: "build" option of Snowpack states the same folder as the hosting.public: "webapp/build" setting of Firebase (in firebase.json here above):

module.exports = {,
  buildOptions: { out: "build"  },};

@olange olange closed this as completed Jan 26, 2021
@olange
Copy link
Owner Author

olange commented Feb 24, 2021

Snowpack has support for monorepo layout and packages linked with npm link or NPM Workspaces:

Try to find an example and change the build pipeline to support such layout.

Reference articles

olange added a commit that referenced this issue May 13, 2021
so to have Snowpack observe the changes to the packages/**,
«mounted» by NPM thru its own 'workspaces' feature.
olange added a commit that referenced this issue May 13, 2021
Avoids dependencies to the @gongfuio/prettierrc for packages
published on NPMJS.
@olange
Copy link
Owner Author

olange commented Apr 26, 2022

We'll need to review our choices, as Snowpack announced last week on their website that they would not actively maintain the project anymore:

« Update (April 20, 2022):

Snowpack is no longer actively maintained and is not recommended for new projects.

Check out Vite for a well-maintained Snowpack alternative.
See also: esbuild, parcel »

I guess there is no urgency, the tooling was mature, adopted and they'll fix security issues for a little while.
And on our side, we're using the Modern Web Dev stack for the ‹h3-worldmap› web component.

I was not far from using that Modern Web Dev tech stack in January 2021, when I first considered which tooling to use — but settled for Snowpack, as it was simpler to setup, with our various project parts.

@olange olange reopened this Apr 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
tooling Toolchain and infrastructure
Projects
None yet
Development

No branches or pull requests

1 participant