refactor: Replace Rollup with Vite (#2656)
This is a high risk change: every byte the card ships is emitted by a
different bundler, minified by a different minifier, and every
stylesheet is compiled by a different sass. The intent is that the
card's behaviour is unchanged.
**Significant development win**: Build time drops from 24s to 1.1s 🎉
Also adds a test suite ('dist') that runs against the built bundle.
This commit is contained in:
+118
@@ -0,0 +1,118 @@
|
||||
import { visualizer } from 'rollup-plugin-visualizer';
|
||||
import { defineConfig } from 'vite';
|
||||
|
||||
import { getBuildDefines } from './scripts/build-defines.js';
|
||||
import { cleanDist } from './scripts/clean-dist-plugin.js';
|
||||
import { facadeEntry } from './scripts/facade-entry-plugin.js';
|
||||
import { PUBLIC_ENTRIES } from './scripts/public-entries.js';
|
||||
import { svgPath } from './scripts/svg-path-plugin.js';
|
||||
|
||||
// `yarn start` passes `--mode development`; a plain `vite build` is
|
||||
// `production`.
|
||||
export default defineConfig(({ mode }) => {
|
||||
const dev = mode === 'development';
|
||||
|
||||
return {
|
||||
define: {
|
||||
// Necessary for xiel/embla-carousel-wheel-gestures
|
||||
// See:https://github.com/xiel/embla-carousel-wheel-gestures/issues/164
|
||||
'process.env.NODE_ENV': JSON.stringify(dev ? 'development' : 'production'),
|
||||
|
||||
...getBuildDefines({ dev, releaseVersion: process.env.RELEASE_VERSION }),
|
||||
},
|
||||
|
||||
plugins: [
|
||||
cleanDist(),
|
||||
svgPath(),
|
||||
facadeEntry({ publicFileNames: PUBLIC_ENTRIES }),
|
||||
visualizer({ filename: 'visualizations/treemap.html', template: 'treemap' }),
|
||||
],
|
||||
|
||||
// `yarn preview` hands the built card out over HTTP, for a Home Assistant that
|
||||
// reads it from a URL rather than from a path on disk. The dev container
|
||||
// forwards this port and its Home Assistant loads the card from it.
|
||||
preview: {
|
||||
host: '0.0.0.0',
|
||||
port: 10001,
|
||||
|
||||
// Fail rather than quietly moving: the port is what the dev container
|
||||
// expects to find the card on.
|
||||
strictPort: true,
|
||||
|
||||
// Home Assistant is served from a different origin than this.
|
||||
cors: true,
|
||||
},
|
||||
|
||||
resolve: {
|
||||
// Same as Vite's default, minus the trailing `jsnext:main` and `jsnext`: an
|
||||
// early convention for naming an ES module build that `module` replaced.
|
||||
// `moment` is the one dependency still shipping it, and honouring it hands
|
||||
// out moment as an ES module, which `vis-timeline`'s CommonJS build cannot
|
||||
// then use -- causing timeline views to throw an error. Requiring an ES
|
||||
// module yields the namespace object rather than moment itself.
|
||||
mainFields: ['browser', 'module'],
|
||||
},
|
||||
|
||||
css: {
|
||||
preprocessorOptions: {
|
||||
scss: {
|
||||
// A couple of stylesheets are pulled in by package name (e.g. `@use
|
||||
// '@graphiteds/core/css/core.css'`). sass resolves a bare name like
|
||||
// that only if node_modules is on its load path.
|
||||
loadPaths: ['./node_modules/'],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
build: {
|
||||
lib: { entry: 'src/card.ts', formats: ['es'] },
|
||||
target: 'es2021',
|
||||
outDir: 'dist',
|
||||
|
||||
// `cleanDist` removes what an earlier build left instead, once the new
|
||||
// output is written, so the directory a running Home Assistant serves the
|
||||
// card from is never briefly empty.
|
||||
emptyOutDir: false,
|
||||
|
||||
minify: dev ? false : 'oxc',
|
||||
sourcemap: dev,
|
||||
|
||||
rolldownOptions: {
|
||||
output: {
|
||||
// The card lives in a hashed chunk that nothing outside the build can
|
||||
// name; `facadeEntry` emits the stable names pointing at it.
|
||||
entryFileNames: '[name]-[hash].js',
|
||||
|
||||
chunkFileNames: (chunk) => {
|
||||
// Name the language chunks for what they hold: the module they are
|
||||
// built from is a bare `de.json`, which says nothing on its own.
|
||||
if (chunk.facadeModuleId?.match(/localize\/languages\/.*\.json/)) {
|
||||
return 'lang-[name]-[hash].js';
|
||||
}
|
||||
// The template engine is imported as `ha-nunjucks/dist`, which would
|
||||
// otherwise name the chunk `dist`.
|
||||
if (chunk.facadeModuleId?.match(/ha-nunjucks/)) {
|
||||
return 'templates-[hash].js';
|
||||
}
|
||||
return '[name]-[hash].js';
|
||||
},
|
||||
|
||||
// Lib mode leaves whitespace in even when minifying.
|
||||
minify: !dev,
|
||||
|
||||
// Rolldown gives a shared module its own chunk regardless of how small
|
||||
// it is, which by default leaves the card fetching dozens of files of a
|
||||
// few hundred bytes before it can start. Instead, gather small shared
|
||||
// modules into one chunk instead; anything larger keeps its own, so the
|
||||
// code behind a dynamic (lazy) imports is still effective.
|
||||
//
|
||||
// Numbers set by trial and error -- large values start pulling in
|
||||
// genuinely "lazy" code into the set that is fetched at startup.
|
||||
codeSplitting: {
|
||||
groups: [{ name: 'shared', maxModuleSize: 6000, minShareCount: 2 }],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
Reference in New Issue
Block a user