Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions packages/vite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,8 @@
"@types/send": "^0.17.4",
"esbuild": "^0.25.0",
"html-minifier-terser": "^7.2.0",
"rolldown-vite": "^7.2.10",
"rollup": "^4.53.3",
"vite": "^7.2.6",
"rolldown": "1.0.0-rc.9",
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kinda silly this is the latest release, but we're just using it for types

"vite": "^8.0.0",
"vitest": "^3.2.4"
},
"files": [
Expand Down
151 changes: 72 additions & 79 deletions packages/vite/src/ember.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { existsSync } from 'fs';
import { templateTag } from './template-tag.js';
import { resolver } from './resolver.js';
import type { UserConfig as ViteUserConfig, ConfigEnv, Plugin } from 'vite';
import type { UserConfig as RolldownUserConfig } from 'rolldown-vite';
import type { ConfigEnv, Plugin } from 'vite';

import { esBuildResolver } from './esbuild-resolver.js';
import { warnRootUrl } from './warn-root-url.js';
import type { ViteUserConfig as UserConfig, Vite8UserConfig } from './types.js';

export let extensions = ['.mjs', '.gjs', '.js', '.mts', '.gts', '.ts', '.hbs', '.hbs.js', '.json'];

Expand All @@ -16,8 +16,9 @@ export const defaultRolldownSharedPlugins = [
'babel',
];

// We support a range of vite versions with different types here
type UserConfig = ViteUserConfig & RolldownUserConfig;
function hasRolldown(pluginContext: any, _config: unknown): _config is Vite8UserConfig {
return Boolean(pluginContext?.meta?.rolldownVersion);
}

export function ember(params?: {
/**
Expand All @@ -37,107 +38,99 @@ export function ember(params?: {
async config(config: UserConfig, env: ConfigEnv) {
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some of this was reorganized so I had an easier time narrowing types with the above hasRolldown fn

// Default vite resolve extensions, which the user can completely
// override if they want
if (!config.resolve) {
config.resolve = {};
}
config.resolve ||= {};
config.build ||= {};
config.server ||= {};
config.optimizeDeps ||= {};
config.optimizeDeps.exclude ||= [];
config.optimizeDeps.extensions ||= [];

if (!config.resolve.extensions) {
config.resolve.extensions = extensions;
}

// Our esbuild integration only works if these extensions are
// configured, so we force them in
if (!config.optimizeDeps) {
config.optimizeDeps = {};
}
if (!config.optimizeDeps.extensions) {
config.optimizeDeps.extensions = [];
}
for (let requiredExt of ['.hbs', '.gjs', '.gts']) {
if (!config.optimizeDeps.extensions.includes(requiredExt)) {
config.optimizeDeps.extensions.push(requiredExt);
}
}

// @embroider/macros needs to not go through dep optimization
if (config.optimizeDeps.exclude) {
config.optimizeDeps.exclude.push('@embroider/macros');
} else {
config.optimizeDeps.exclude = ['@embroider/macros'];
}

// @ts-expect-error the types aren't finished yet it would seem
if (this?.meta?.rolldownVersion) {
// configure our embroider resolver for optimize deps
if (!config.optimizeDeps.rollupOptions) {
config.optimizeDeps.rollupOptions = {};
}

const emberRollupPlugins = sharedRolldownPlugins(
params?.rolldownSharedPlugins ?? defaultRolldownSharedPlugins,
config.plugins
);

if (config.optimizeDeps.rollupOptions.plugins) {
if (Array.isArray(config.optimizeDeps.rollupOptions.plugins)) {
config.optimizeDeps.rollupOptions.plugins.push(...emberRollupPlugins);
} else {
throw new Error('Could not automatically configure the Ember plugin for optimizeDeps');
}
} else {
config.optimizeDeps.rollupOptions.plugins = emberRollupPlugins;
config.optimizeDeps.exclude.push('@embroider/macros');

const emberRollupPlugins = sharedRolldownPlugins(
params?.rolldownSharedPlugins ?? defaultRolldownSharedPlugins,
config.plugins
);

if (hasRolldown(this, config)) {
/**
* Vite 8 and higher
*/
config.optimizeDeps.rolldownOptions ||= {};
config.optimizeDeps.rolldownOptions.plugins ||= [];
if (!Array.isArray(config.optimizeDeps.rolldownOptions.plugins)) {
throw new Error(
'Could not automatically configure the Ember plugin for optimizeDeps. optimizeDeps.rolldownOptions.plugins must be an array.'
);
}
config.optimizeDeps.rolldownOptions.plugins.push(...emberRollupPlugins);

if (!config.optimizeDeps.rollupOptions.resolve) {
config.optimizeDeps.rollupOptions.resolve = {};
}
config.optimizeDeps.rollupOptions.resolve.extensions = extensions;
config.optimizeDeps.rolldownOptions.resolve ||= {};
config.optimizeDeps.rolldownOptions.resolve.extensions = extensions;
} else {
// configure out esbuild resolver
if (!config.optimizeDeps.esbuildOptions) {
config.optimizeDeps.esbuildOptions = {};
}

if (config.optimizeDeps.esbuildOptions.plugins) {
config.optimizeDeps.esbuildOptions.plugins.push(esBuildResolver());
} else {
config.optimizeDeps.esbuildOptions.plugins = [esBuildResolver()];
}
}

if (!config.build) {
config.build = {};
}

if (!config.build.rollupOptions) {
config.build.rollupOptions = {};
/**
* Vite 7 and lower
*/
config.optimizeDeps.esbuildOptions ||= {};
config.optimizeDeps.esbuildOptions.plugins ||= [];
config.optimizeDeps.esbuildOptions.plugins.push(esBuildResolver());
}

// we provide a default build.rollupOptions.input that builds index.html
// and, in non-production or when forcing tests, tests/index.html. But
// the user may choose to take charge of input entirely.
if (!config.build.rollupOptions.input) {
let hasRootEntry = existsSync('index.html');
let hasTestsEntry = existsSync('tests/index.html');
let hasRootEntry = existsSync('index.html');
let hasTestsEntry = existsSync('tests/index.html');

config.build.rollupOptions.input = {};
if (!config.build.rolldownOptions?.input) {
if (hasRolldown(this, config)) {
config.build.rolldownOptions ||= {};

if (hasRootEntry) {
Object.assign(config.build.rollupOptions.input, {
main: 'index.html',
});
}
if (hasRootEntry) {
config.build.rolldownOptions.input ||= {};
Object.assign(config.build.rolldownOptions.input, {
main: 'index.html',
});
}

if (hasTestsEntry) {
if (shouldBuildTests(env.mode)) {
config.build.rolldownOptions.input ||= {};
Object.assign(config.build.rolldownOptions.input, {
tests: 'tests/index.html',
});
}
}
} else {
config.build.rollupOptions ||= {};

if (hasTestsEntry) {
if (shouldBuildTests(env.mode)) {
if (hasRootEntry) {
config.build.rollupOptions.input ||= {};
Object.assign(config.build.rollupOptions.input, {
tests: 'tests/index.html',
main: 'index.html',
});
}
}
}

if (!config.server) {
config.server = {};
if (hasTestsEntry) {
if (shouldBuildTests(env.mode)) {
config.build.rollupOptions.input ||= {};
Object.assign(config.build.rollupOptions.input, {
tests: 'tests/index.html',
});
}
}
}
}

// Traditional ember development port as default.
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/hbs.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { PluginContext } from 'rollup';
import type { Plugin } from 'vite';
import { hbsToJS, templateOnlyComponentSource } from '@embroider/core';
import { extFilter, supportsObjectHooks } from './build-id-filter.js';
import type { PluginContext } from 'rolldown';

export const hbsFilter = extFilter('hbs');

Expand Down
4 changes: 2 additions & 2 deletions packages/vite/src/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import core from '@embroider/core';
import { resolve } from 'path';

const { cleanUrl, getUrlQueryParams, packageName } = core;
import type { PluginContext, ResolveIdResult } from 'rollup';
import type { PluginContext, ResolveIdResult } from 'rolldown';
import type { BackChannel } from './backchannel.js';
import { assertNever } from 'assert-never';
import { externalName } from '@embroider/reverse-exports';
Expand Down Expand Up @@ -103,7 +103,7 @@ export class RollupRequestAdapter implements RequestAdapter<Resolution<ResolveId
virtualResponse(
request: ModuleRequest<Resolution<ResolveIdResult>>,
virtual: VirtualResponse
): Resolution<ResolveIdResult> {
): Resolution<ResolveIdResult & { resolvedBy: string }> {
Comment thread
void-mAlex marked this conversation as resolved.
return {
type: 'found',
filename: virtual.specifier,
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { assertNever } from 'assert-never';
import makeDebug from 'debug';
import { join, normalize, resolve } from 'path';
import { writeStatus } from './backchannel.js';
import type { PluginContext, ResolveIdResult } from 'rollup';
import type { PluginContext, ResolveIdResult } from 'rolldown';
import { externalName } from '@embroider/reverse-exports';
import fs from 'fs-extra';
import { createHash } from 'crypto';
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/scripts.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Plugin } from 'vite';
import type { EmittedFile } from 'rollup';
import type { EmittedFile } from 'rolldown';
import { JSDOM } from 'jsdom';
import fs from 'fs-extra';
const { readFileSync, readJSONSync, existsSync } = fs;
Expand Down
51 changes: 51 additions & 0 deletions packages/vite/src/types.ts
Comment thread
void-mAlex marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import type { UserConfig as ActualViteUserConfig } from 'vite';

/**
* We support a range of vite versions with different types here
*
* These subconfigs are minimally what we use, as we don't want to maintain
* types for someone else's package.
*
* This exists at all because we support vite 5 through vite 8 (as of 2025-03-17)
* and there isn't a package with these types available for us.
* The types are internal only, and we *should* have enough testing where if we mess
* something up, runtime catches us.
*/
export type ViteUserConfig = (ActualViteUserConfig & Vite8UserConfig) | (ActualViteUserConfig & Vite7UserConfig);

/**
* The sub-types for things we configure in src/ember.ts
*
* I expect htis sort of plucking types to be sufficient for our use case,
* because Vite's configure only renamed and moved a couple things we're using,
* and they are roughly (or exactly) the same shape of things
*/
type RolldownOptions = NonNullable<NonNullable<ActualViteUserConfig['optimizeDeps']>['rolldownOptions']>;
type Resolve = RolldownOptions['resolve'];
type Plugins = RolldownOptions['plugins'];

/**
* Subset of:
* https://npmx.dev/package-code/vite/v/8.0.0/dist%2Fnode%2Findex.d.ts
*
* (but since the current version *is* 8, we only need the brand type here)
*/
export interface Vite8UserConfig {
// Private brand type
__vite8__: true;
}

/**
* Subset of:
* https://npmx.dev/package-code/vite/v/7.3.1/dist%2Fnode%2Findex.d.ts
*/
interface Vite7UserConfig {
optimizeDeps?: {
esbuildOptions?: {
resolve?: Resolve;
plugins?: Plugins;
};
};
// Private brand type
__vite7__: true;
}
Loading
Loading