Skip to content

Commit

Permalink
fix: upgrade to vite 4.4.9 (#354)
Browse files Browse the repository at this point in the history
Fixes #351
  • Loading branch information
chrispcampbell authored Sep 5, 2023
1 parent f132c8d commit db975fa
Show file tree
Hide file tree
Showing 21 changed files with 579 additions and 229 deletions.
1 change: 1 addition & 0 deletions examples/hello-world/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"private": true,
"type": "module",
"scripts": {
"clean": "rm -rf ./sde-prep",
"build": "sde bundle",
"dev": "sde dev",
"save-baseline": "sde-check baseline --save",
Expand Down
4 changes: 2 additions & 2 deletions examples/sample-check-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@
"@sdeverywhere/sample-check-tests": "workspace:*"
},
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^1.0.8",
"@sveltejs/vite-plugin-svelte": "^2.4.5",
"postcss": "^8.2.14",
"pug": "^3.0.1",
"sass": "^1.34.1",
"svelte": "^3.59.2",
"svelte-check": "^3.5.1",
"svelte-preprocess": "^5.0.4",
"vite": "^3.1.3"
"vite": "^4.4.9"
},
"author": "Climate Interactive",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion examples/sample-check-bundle/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"assert-never": "^1.2.1"
},
"devDependencies": {
"vite": "^3.1.3"
"vite": "^4.4.9"
},
"author": "Climate Interactive",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion examples/sample-check-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"assert-never": "^1.2.1"
},
"devDependencies": {
"vite": "^3.1.3"
"vite": "^4.4.9"
},
"author": "Climate Interactive",
"license": "MIT",
Expand Down
2 changes: 1 addition & 1 deletion examples/template-default/packages/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@
},
"devDependencies": {
"@types/chart.js": "^2.9.34",
"vite": "^3.1.3"
"vite": "^4.4.9"
}
}
2 changes: 1 addition & 1 deletion examples/template-default/packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@
"@sdeverywhere/runtime-async": "^0.2.0"
},
"devDependencies": {
"vite": "^3.1.3"
"vite": "^4.4.9"
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
"typedoc": "0.25.0",
"typedoc-plugin-markdown": "3.16.0",
"typescript": "^5.2.2",
"vitest": "^0.23.4"
"vitest": "^0.34.3"
},
"pnpm": {
"peerDependencyRules": {
Expand Down
4 changes: 2 additions & 2 deletions packages/check-ui-shell/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
"fontfaceobserver": "^2.1.0"
},
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^1.0.8",
"@sveltejs/vite-plugin-svelte": "^2.4.5",
"@types/chart.js": "^2.9.34",
"@types/fontfaceobserver": "^0.0.6",
"postcss": "^8.2.14",
Expand All @@ -46,7 +46,7 @@
"svelte-awesome": "^3.0.0",
"svelte-check": "^3.5.1",
"svelte-preprocess": "^5.0.4",
"vite": "^3.1.3"
"vite": "^4.4.9"
},
"devDependenciesComments": {
"svelte-awesome": [
Expand Down
4 changes: 2 additions & 2 deletions packages/plugin-check/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
},
"dependencies": {
"@rollup/plugin-node-resolve": "^13.3.0",
"@rollup/plugin-replace": "^4.0.0",
"@rollup/plugin-replace": "^5.0.2",
"@sdeverywhere/check-core": "^0.1.1",
"@sdeverywhere/check-ui-shell": "^0.2.2",
"@sdeverywhere/runtime": "^0.2.0",
Expand All @@ -47,7 +47,7 @@
"chokidar": "^3.5.3",
"picocolors": "^1.0.0",
"rollup": "^2.76.0",
"vite": "^3.1.3"
"vite": "4.4.9"
},
"dependenciesComments": {
"rollup": [
Expand Down
83 changes: 76 additions & 7 deletions packages/plugin-check/src/vite-config-for-bundle.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Copyright (c) 2022 Climate Interactive / New Venture Fund

import { existsSync, statSync } from 'fs'
import { dirname, join as joinPath, relative, resolve as resolvePath } from 'path'
import { basename, dirname, join as joinPath, relative, resolve as resolvePath } from 'path'
import { fileURLToPath } from 'url'

import type { InlineConfig, Plugin as VitePlugin } from 'vite'
import type { InlineConfig, ResolvedConfig, Plugin as VitePlugin } from 'vite'
import { nodeResolve } from '@rollup/plugin-node-resolve'

import type { ModelSpec } from '@sdeverywhere/build'
Expand Down Expand Up @@ -93,6 +93,55 @@ export const dataSizeInBytes = ${dataSizeInBytes};
}
}

/**
* XXX: This overrides the built-in `vite:resolve` plugin so that we can intercept `resolveId`
* calls for the threads package.
*/
function overrideViteResolvePlugin(viteConfig: ResolvedConfig) {
const resolvePlugin = viteConfig.plugins.find(p => p.name === 'vite:resolve')
if (resolvePlugin === undefined) {
throw new Error('Failed to locate the built-in vite:resolve plugin')
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const originalResolveId = resolvePlugin.resolveId as any
resolvePlugin.resolveId = async function resolveId(id, importer, options) {
if (id.startsWith('./implementation') && importer.includes('threads/dist-esm')) {
// XXX: The default resolver behavior will look at the `browser` mappings in
// `threads/package.json` and try to resolve `implementation.js` to
// `implementation.browser.js` because it thinks we're in a browser-only context.
// We don't want that. Instead we want to keep the generic implementation from
// threads that chooses between the Node and browser implementations at runtime.
//
// If we get here, importer will be something like:
// /.../node_modules/.pnpm/[email protected]/node_modules/threads/dist-esm/{worker,master}/index.js
// And id will be:
// ./implementation
// So resolve the ID to:
// /.../node_modules/.pnpm/[email protected]/node_modules/threads/dist-esm/{worker,master}/implementation.js
//
// Or, importer will be:
// /.../node_modules/.pnpm/[email protected]/node_modules/threads/dist-esm/{worker,master}/implementation.js
// And id will be one of:
// ./implementation.browser
// ./implementation.node
// ./implementation.worker_threads
// So resolve the ID to:
// /.../node_modules/.pnpm/[email protected]/node_modules/threads/dist-esm/{worker,master}/implementation.{...}.js
const idFileName = id.replace('./', '')
const importerFileName = basename(importer)
const resolvedId = importer.replace(importerFileName, `${idFileName}.js`)
return {
id: resolvedId,
moduleSideEffects: false
}
}

// For all other cases, fall back on the default resolver
return originalResolveId.call(this, id, importer, options)
}
}

export async function createViteConfigForBundle(prepDir: string, modelSpec: ModelSpec): Promise<InlineConfig> {
// Use `template-bundle` as the root directory for the bundle project
const root = resolvePath(__dirname, '..', 'template-bundle')
Expand Down Expand Up @@ -130,8 +179,15 @@ export async function createViteConfigForBundle(prepDir: string, modelSpec: Mode
// XXX: Prevent Vite from using the `browser` section of `threads/package.json`
// since we want to force the use of the general module (under dist-esm) that chooses
// the correct implementation (Web Worker vs worker_threads) at runtime. Currently
// Vite's library mode is browser focused, so using a `customResolver` seems to be
// the easiest way to prevent Vite from picking up the `browser` exports.
// Vite's library mode is browser focused and generally chooses the right imports,
// except in the case of the threads package where we want to use the generic
// `implementation.js` that chooses between Web Worker and worker_threads at runtime.
// Note that we could in theory set `resolve.browserField` to false, but that would
// make Vite not use the browser field for all other packages, and there is not
// currently a way to tell Vite to use the browser field on a case-by-case basis.
// So for now we need this workaround here to make it resolve to `dist-esm`, and then
// a second workaround in `overrideViteResolvePlugin` to prevent the resolver from
// using the browser field when resolving the threads package.
{
find: 'threads',
replacement: 'threads',
Expand All @@ -153,7 +209,17 @@ export async function createViteConfigForBundle(prepDir: string, modelSpec: Mode

plugins: [
// Use a virtual module plugin to inject the model spec values
injectModelSpec(prepDir, modelSpec)
injectModelSpec(prepDir, modelSpec),

// XXX: Install a wrapper around the built-in `vite:resolve` plugin so that we can
// override the default resolver behavior that tries to resolve the `browser` section
// of the `package.json` for the threads package.
{
name: 'vite-plugin-override-resolve',
configResolved(viteConfig) {
overrideViteResolvePlugin(viteConfig)
}
}
],

build: {
Expand All @@ -162,6 +228,9 @@ export async function createViteConfigForBundle(prepDir: string, modelSpec: Mode
outDir,
emptyOutDir: false,

// Uncomment for debugging purposes
// minify: false,

lib: {
entry: './src/index.ts',
formats: ['es'],
Expand All @@ -177,8 +246,8 @@ export async function createViteConfigForBundle(prepDir: string, modelSpec: Mode
// in its Node implementation. This import ensures that threads.js uses
// the native `worker_threads` implementation when using the bundle in a
// Node environment. When importing the bundle for use in the browser,
// Vite will transform this import into an empty module (it does not seem
// to be necessary to define a polyfill).
// Vite will transform this import into an empty module due to the empty
// polyfill that is configured in `vite-config-for-report.ts`.
output: {
banner: `
import * as worker_threads from 'worker_threads'
Expand Down
27 changes: 15 additions & 12 deletions packages/plugin-check/src/vite-config-for-report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,26 +107,26 @@ export function createViteConfigForReport(
// find a less fragile solution.
include: [
// from check-core
'assert-never',
'ajv',
'neverthrow',
'yaml',
'@sdeverywhere/check-core > assert-never',
'@sdeverywhere/check-core > ajv',
'@sdeverywhere/check-core > neverthrow',
'@sdeverywhere/check-core > yaml',
// from check-ui-shell
'fontfaceobserver',
'copy-text-to-clipboard',
'chart.js'
'@sdeverywhere/check-ui-shell > fontfaceobserver',
'@sdeverywhere/check-ui-shell > copy-text-to-clipboard',
'@sdeverywhere/check-ui-shell > chart.js'
],

exclude: [
// XXX: The threads.js implementation references `tiny-worker` as an optional
// dependency, but it doesn't get used at runtime, so we can just exclude it
// so that Vite doesn't complain in dev mode
'tiny-worker',
'tiny-worker'

// XXX: Similarly, chart.js treats `moment` as an optional dependency, but we
// don't use it at runtime; we need to exclude it here, otherwise Vite will
// complain about missing dependencies in dev mode
'moment'
// 'moment'
]
},

Expand All @@ -150,9 +150,11 @@ export function createViteConfigForReport(
// implementation of threads.js; this allows us to use one bundle that works in both
// Node and browser environments
noopPolyfillAlias('events'),
noopPolyfillAlias('fs'),
noopPolyfillAlias('os'),
noopPolyfillAlias('path'),
noopPolyfillAlias('url')
noopPolyfillAlias('url'),
noopPolyfillAlias('worker_threads')
]
},

Expand All @@ -175,11 +177,12 @@ export function createViteConfigForReport(
// the glob handler (which requires the glob to be injected as a literal)
replace({
preventAssignment: true,
delimiters: ['', ''],
values: {
// Inject the path for baseline bundles
__BASELINE_BUNDLES_PATH__: JSON.stringify(baselinesPath)
'./__BASELINE_BUNDLES_PATH__': baselinesPath
}
}) as PluginOption
}) as unknown as PluginOption
],

build: {
Expand Down
22 changes: 16 additions & 6 deletions packages/plugin-check/src/vite-config-for-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import { dirname, relative, resolve as resolvePath } from 'path'
import { fileURLToPath } from 'url'

import type { InlineConfig } from 'vite'
import type { InlineConfig, PluginOption } from 'vite'
import replace from '@rollup/plugin-replace'

const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
Expand Down Expand Up @@ -44,11 +45,20 @@ export function createViteConfigForTests(projDir: string, prepDir: string, mode:
// TODO: Disable vite output by default?
// logLevel: 'silent',

// Inject special values into the generated JS
define: {
// Inject the glob pattern for matching check yaml files
__YAML_PATH__: JSON.stringify(yamlPath)
},
plugins: [
// Inject special values into the generated JS
// TODO: We currently have to use `@rollup/plugin-replace` instead of Vite's
// built-in `define` feature because the latter does not seem to run before
// the glob handler (which requires the glob to be injected as a literal)
replace({
preventAssignment: true,
delimiters: ['', ''],
values: {
// Inject the glob pattern for matching check yaml files
'./__YAML_PATH__': yamlPath
}
}) as unknown as PluginOption
],

build: {
// Write output files to the configured directory (instead of the default `dist`);
Expand Down
1 change: 0 additions & 1 deletion packages/plugin-check/template-report/src/env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

// These values are injected by Vite at build time, so we need to
// declare types for them here
declare const __BASELINE_BUNDLES_PATH__: string
declare const __BASELINE_NAME__: string
declare const __CURRENT_NAME__: string
declare const __SUITE_SUMMARY_JSON__: string
10 changes: 7 additions & 3 deletions packages/plugin-check/template-report/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,18 @@ const availableBundles: { [key: string]: LoadBundle } = {}
let bundleNames: string[]
let selectedBaselineBundleName: string
let selectedCurrentBundleName: string
const baselinesPath = __BASELINE_BUNDLES_PATH__
// The following value will be injected by `vite-config-for-report.ts`
const baselinesPath = './__BASELINE_BUNDLES_PATH__'
if (import.meta.hot && baselinesPath) {
// Restore the previously selected bundles (from before the page was reloaded)
selectedBaselineBundleName = loadBundleName('baseline')
selectedCurrentBundleName = loadBundleName('current')

// Get the available baseline bundles
const bundlesGlob = import.meta.glob(__BASELINE_BUNDLES_PATH__, {
// Get the available baseline bundles. The `./__BASELINE_BUNDLES_PATH__` part
// will be replaced by Vite (see `vite-config-for-report.ts`). Note that we
// provide a placeholder here that looks like a valid glob pattern, since Vite's
// dependency resolver will report errors if it is invalid (not a literal).
const bundlesGlob = import.meta.glob('./__BASELINE_BUNDLES_PATH__', {
eager: false
})
const baselineBundleNames: string[] = []
Expand Down
5 changes: 0 additions & 5 deletions packages/plugin-check/template-tests/src/env.d.ts

This file was deleted.

7 changes: 5 additions & 2 deletions packages/plugin-check/template-tests/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ import type {
InputVar
} from '@sdeverywhere/check-core'

// Load the yaml test files
const yamlGlob = import.meta.glob(__YAML_PATH__, {
// Load the yaml test files. The `./__YAML_PATH__` part will be replaced by Vite
// (see `vite-config-for-tests.ts`). Note that we provide a placeholder here that
// looks like a valid glob pattern, since Vite's dependency resolver will report
// errors if it is invalid (not a literal).
const yamlGlob = import.meta.glob('./__YAML_PATH__', {
eager: true,
as: 'raw'
})
Expand Down
4 changes: 2 additions & 2 deletions packages/plugin-vite/docs/interfaces/VitePluginOptions.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ Specifies the behavior of the plugin for different `sde` build modes.

| Name | Type |
| :------ | :------ |
| `development?` | ``"watch"`` \| ``"serve"`` \| ``"skip"`` \| ``"post-generate"`` \| ``"post-build"`` |
| `development?` | ``"serve"`` \| ``"watch"`` \| ``"skip"`` \| ``"post-generate"`` \| ``"post-build"`` |
| `production?` | ``"skip"`` \| ``"post-generate"`` \| ``"post-build"`` |

**development?**: ``"watch"`` \| ``"serve"`` \| ``"skip"`` \| ``"post-generate"`` \| ``"post-build"``
**development?**: ``"serve"`` \| ``"watch"`` \| ``"skip"`` \| ``"post-generate"`` \| ``"post-build"``

The behavior of the plugin when sde is configured for development mode.

Expand Down
Loading

0 comments on commit db975fa

Please sign in to comment.