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

Add Prototype Vite Packager #759

Closed
Closed
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
4 changes: 4 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
/packages/webpack/**/*.d.ts
/packages/hbs-loader/**/*.js
/packages/hbs-loader/**/*.d.ts
/packages/rollup-plugin-hbs/**/*.js
/packages/rollup-plugin-hbs/**/*.d.ts
/packages/vite/**/*.js
/packages/vite/**/*.d.ts
/test-packages/support/**/*.js
/test-packages/**/*.d.ts
/tests/scenarios/**/*.js
Expand Down
7 changes: 7 additions & 0 deletions packages/rollup-plugin-hbs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/node_modules
/src/**/*.js
/src/**/*.d.ts
/src/**/*.map
/*/tests/**/*.js
/*/tests/**/*.d.ts
/*/tests/**/*.map
36 changes: 36 additions & 0 deletions packages/rollup-plugin-hbs/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"name": "@embroider/rollup-plugin-hbs",
"version": "0.42.3",
"private": false,
"description": "Glimmer handlebars plugin for Rollup",
"repository": {
"type": "git",
"url": "https://github.com/embroider-build/embroider.git",
"directory": "packages/rollup-plugin-hbs"
},
"license": "MIT",
"author": "Alex LaFroscia",
"main": "src/index.js",
"files": [
"src/**/*.js",
"src/**/*.d.ts",
"src/**/*.js.map"
],
"scripts": {
"prepare": "tsc"
},
"peerDependencies": {
"@embroider/core": "0.42.3"
},
"devDependencies": {
"@embroider/core": "0.42.3",
"rollup": "^2.52.6",
"typescript": "~4.0.0"
},
"engines": {
"node": "10.* || 12.* || >= 14"
},
"volta": {
"extends": "../../package.json"
}
}
25 changes: 25 additions & 0 deletions packages/rollup-plugin-hbs/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { parse } from 'path';
import type { Plugin as RollupPlugin } from 'rollup';
import { applyVariantToTemplateCompiler, Variant } from '@embroider/core';

export interface Options {
templateCompilerFile: string;
variant: Variant;
}

export default function glimmerTemplateCompilerPlugin({ templateCompilerFile, variant }: Options): RollupPlugin {
// eslint-disable-next-line @typescript-eslint/no-require-imports
const templateCompiler = applyVariantToTemplateCompiler(variant, require(templateCompilerFile)).compile;

return {
name: '@embroider/rollup-plugin-hbs',

transform(src, id) {
const parsedFilePath = parse(id);

if (parsedFilePath.ext === '.hbs') {
return templateCompiler(id, src);
}
},
};
}
7 changes: 7 additions & 0 deletions packages/vite/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/node_modules
/src/**/*.js
/src/**/*.d.ts
/src/**/*.map
/*/tests/**/*.js
/*/tests/**/*.d.ts
/*/tests/**/*.map
42 changes: 42 additions & 0 deletions packages/vite/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"name": "@embroider/vite",
"version": "0.42.3",
"private": false,
"description": "Builds EmberJS apps with Vite",
"repository": {
"type": "git",
"url": "https://github.com/embroider-build/embroider.git",
"directory": "packages/vite"
},
"license": "MIT",
"author": "Alex LaFroscia",
"main": "src/index.js",
"files": [
"src/**/*.js",
"src/**/*.d.ts",
"src/**/*.js.map"
],
"scripts": {
"prepare": "tsc"
},
"dependencies": {
"@embroider/rollup-plugin-hbs": "0.42.3",
"@rollup/plugin-babel": "^5.3.0",
"fs-extra": "^7.0.0"
},
"peerDependencies": {
"@embroider/core": "^0.39.1",
"vite": "^2.0.0"
},
"devDependencies": {
"@embroider/core": "0.42.3",
"typescript": "~4.0.0",
"vite": "^2.3.8"
},
"engines": {
"node": "12.* || 14.* || >= 16"
},
"volta": {
"extends": "../../package.json"
}
}
136 changes: 136 additions & 0 deletions packages/vite/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import { realpathSync } from 'fs';
import { copyFile } from 'fs-extra';
import { join } from 'path';
import {
HTMLEntrypoint,
Packager,
PackagerConstructor,
Variant,
applyVariantToBabelConfig,
getAppMeta,
getPackagerCacheDir,
} from '@embroider/core';
import { build } from 'vite';
import templateCompilerPlugin from '@embroider/rollup-plugin-hbs';
import { babel } from '@rollup/plugin-babel';
import { AllowedViteConfig, Options } from './options';

const Vite: PackagerConstructor<Options> = class Vite implements Packager {
static annotation = '@embroider/vite';

private pathToVanillaApp: string;
private variant: Variant;
private viteConfig: AllowedViteConfig;

constructor(
inputPath: string,
private outputPath: string,
variants: Variant[],
_consoleWrite: (msg: string) => void,
options?: Options
) {
this.pathToVanillaApp = realpathSync(inputPath);

// For now we're not worried about building each variant
// Let's just assume we have one
this.variant = variants[0];

this.viteConfig = options?.viteConfig ?? {};
}

async build(): Promise<void> {
const meta = getAppMeta(this.pathToVanillaApp);
const entrypoints: HTMLEntrypoint[] = [];
const otherAssets: string[] = [];
const rootURL = meta['root-url'];

for (let relativePath of meta.assets) {
if (/\.html/i.test(relativePath)) {
entrypoints.push(new HTMLEntrypoint(this.pathToVanillaApp, rootURL, '/', relativePath));
} else {
otherAssets.push(relativePath);
}
}

await build({
// Options we want to override the defaults for, but users can override themselves, too
logLevel: 'error',

// User options
...this.viteConfig,

// Options we *don't* want to allow users to override
base: meta['root-url'],
cacheDir: getPackagerCacheDir('vite'),
configFile: false,
mode: this.variant.optimizeForProduction ? 'production' : 'development',
resolve: {
...this.viteConfig.resolve,
extensions: meta['resolvable-extensions'],
},
root: this.pathToVanillaApp,

build: {
...this.viteConfig.build,
outDir: this.outputPath,
rollupOptions: {
...this.viteConfig.build?.rollupOptions,
input: entrypoints.map(entry => join(this.pathToVanillaApp, entry.filename)),
},
commonjsOptions: {
...this.viteConfig.build?.commonjsOptions,
extensions: meta['resolvable-extensions'],
include: [/.*/],
},
},

plugins: [
templateCompilerPlugin({
templateCompilerFile: join(this.pathToVanillaApp, meta['template-compiler'].filename),
variant: this.variant,
}),

babel({
// Embroider includes the Runtime plugin in the generated Babel config
babelHelpers: 'runtime',

// Path to the Embroider-generated file defining a filtering function
// eslint-disable-next-line @typescript-eslint/no-require-imports
filter: require(join(this.pathToVanillaApp, meta.babel.fileFilter)),

// Add the Babel config produced by Embroider
...this.getBabelConfig(meta.babel.filename),
}),

...(this.viteConfig.plugins ?? []),
],
});

await Promise.all([
// Vite does not process non-module scripts, so we need to copy them over
...entrypoints
.reduce((acc, entrypoint) => [...acc, ...entrypoint.scripts], [] as string[])
.map(script => this.copyThrough(script)),

// Copy over other assets
// This more-or-less mimics what Vite does for `public` files
...otherAssets.map(relativePath => this.copyThrough(relativePath)),
]);
}

private copyThrough(path: string) {
const source = join(this.pathToVanillaApp, path);
const dest = join(this.outputPath, path);

return copyFile(source, dest);
}

private getBabelConfig(configFileName: string) {
const appBabelConfigPath = join(this.pathToVanillaApp, configFileName);

// eslint-disable-next-line @typescript-eslint/no-require-imports
return applyVariantToBabelConfig(this.variant, require(appBabelConfigPath));
}
};

export { Vite };
26 changes: 26 additions & 0 deletions packages/vite/src/options.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { BuildOptions, InlineConfig } from 'vite';

type CommonJSOptions = Required<BuildOptions['commonjsOptions']>;
type ResolveOptions = Required<InlineConfig['resolve']>;
type RollupOptions = Required<BuildOptions['rollupOptions']>;

type AllowedCommonJSOptions = Omit<CommonJSOptions, 'extensions' | 'include'>;
type AllowedResolveOptions = Omit<ResolveOptions, 'extensions'>;
type AllowedRollupOptions = Omit<RollupOptions, 'input'>;

type AllowedBuildOptions = Omit<BuildOptions, 'commonjsOptions' | 'outDir' | 'rollupOptions'> & {
commonjsOptions?: AllowedCommonJSOptions;
rollupOptions?: AllowedRollupOptions;
};

export type AllowedViteConfig = Omit<
InlineConfig,
'base' | 'build' | 'cacheDir' | 'configFile' | 'mode' | 'resolve' | 'root'
> & {
build?: AllowedBuildOptions;
resolve?: AllowedResolveOptions;
};

export interface Options {
viteConfig?: AllowedViteConfig;
}
16 changes: 16 additions & 0 deletions test-packages/support/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,22 @@ export function definesPattern(runtimeName: string, buildTimeName: string): RegE
);
}

const PACKAGERS = ['@embroider/vite', '@embroider/webpack'];

export function fetchPackagerFromDependencies(app: any) {
let Packager;

for (const packagerName of PACKAGERS) {
if (app.project.pkg.devDependencies[packagerName]) {
Packager = require(packagerName);
}
}

return {
Packager,
};
}

export { Project } from './project';
export { default as BuildResult } from './build';
export { expectFilesAt, ExpectFile } from './file-assertions';
5 changes: 3 additions & 2 deletions tests/app-template/ember-cli-build.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
'use strict';

const EmberApp = require('ember-cli/lib/broccoli/ember-app');
const { fetchPackagerFromDependencies } = require('@embroider/test-support');

module.exports = function (defaults) {
let app = new EmberApp(defaults, {
Expand All @@ -20,8 +21,8 @@ module.exports = function (defaults) {
// please specify an object with the list of modules as keys
// along with the exports of each module as its value.

const { Webpack } = require('@embroider/webpack');
return require('@embroider/compat').compatBuild(app, Webpack, {
const { Packager } = fetchPackagerFromDependencies(app);
return require('@embroider/compat').compatBuild(app, Packager, {
skipBabel: [
{
package: 'qunit',
Expand Down
2 changes: 1 addition & 1 deletion tests/app-template/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
"@ember/test-helpers": "^2.2.5",
"@embroider/compat": "0.42.3",
"@embroider/core": "0.42.3",
"@embroider/webpack": "0.42.3",
"@embroider/router": "0.42.3",
"@embroider/test-support": "0.36.0",
"@glimmer/component": "^1.0.4",
"@glimmer/tracking": "^1.0.4",
"babel-eslint": "^10.1.0",
Expand Down
2 changes: 2 additions & 0 deletions tests/scenarios/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
"license": "MIT",
"devDependencies": {
"@embroider/macros": "0.42.3",
"@embroider/vite": "0.42.3",
"@embroider/webpack": "0.42.3",
"bootstrap": "^4.3.1",
"broccoli-funnel": "^3.0.5",
"broccoli-merge-trees": "^3.0.2",
Expand Down
25 changes: 19 additions & 6 deletions tests/scenarios/scenarios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,26 @@ async function release(project: Project) {
project.linkDevDependency('ember-cli', { baseDir: __dirname, resolveName: 'ember-cli-latest' });
}

async function packager_vite(project: Project) {
project.linkDevDependency('@embroider/vite', { baseDir: __dirname });
}

async function packager_webpack(project: Project) {
project.linkDevDependency('@embroider/webpack', { baseDir: __dirname });
}

export function supportMatrix(scenarios: Scenarios) {
return scenarios.expand({
lts_3_16,
lts_3_20,
lts_3_24,
release,
});
return scenarios
.expand({
lts_3_16,
lts_3_20,
lts_3_24,
release,
})
.expand({
packager_vite,
packager_webpack,
});
}

export const appScenarios = supportMatrix(Scenarios.fromDir(dirname(require.resolve('../app-template/package.json'))));
Loading