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 Vite support #33

Merged
merged 3 commits into from
Dec 15, 2024
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
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,13 @@
"fetch-assets": "ts-node fetch_assets/src/main.ts",
"test-screenshots": "ts-node test/screenshot.ts",
"start": "parcel serve",
"start:vite": "vite preview",
"build": "parcel build --public-url '.'",
"build:vite": "vite build",
"postbuild": "workbox generateSW",
"postbuild:vite": "workbox generateSW",
"fullbuild": "yarn run fetch-assets && yarn run build",
"fullbuild:vite": "yarn run fetch-assets && yarn run build:vite",
"lint": "eslint src fetch_assets test",
"fmt": "prettier --write --list-different .",
"typecheck": "tsc --noEmit",
Expand All @@ -37,6 +41,7 @@
"@types/react": "^18.2.7",
"@types/react-dom": "^18.2.4",
"@types/sharp": "^0.31.0",
"@vitejs/plugin-react": "~4.3.4",
"assert": "^2.0.0",
"crypto-browserify": "^3.12.0",
"eslint": "^9.12.0",
Expand All @@ -59,6 +64,7 @@
"typescript-eslint": "^8.10.0",
"url": "^0.11.0",
"util": "^0.12.3",
"vite": "6.0.3",
"vm-browserify": "^1.1.2",
"workbox-cli": "^7.0.0"
},
Expand Down
27 changes: 27 additions & 0 deletions src/js/character_icons_vite.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* character_icon.tsx contains a glob import that only works in Parcel.
* vite.config.ts replaces that Parcel glob import by loading this file instead.
* This file contains a glob import that only works in Vite.
*/

// Return a map of the form { "Icon_<id>": <url> }.
const images = Object.fromEntries(
Object.entries(
// `import.meta.glob` is a Vite-specific feature.
// @ts-expect-error TODO: Can use "vite/client" types after removing conflicting definition in `assets/globals.d.ts`
import.meta.glob("../../assets/icons/*.webp", {
eager: true,
query: "?url",
import: "default",
}),
)
.map(([path, module]) => {
const iconName = path.match(/(Icon_.*)\.webp$/);
if (!iconName || !iconName[1]) {
return null;
}
return [iconName[1], module];
})
.filter((entry) => entry !== null),
);
export default images;
3 changes: 3 additions & 0 deletions src/js/components/character_icon.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
// This is a Parcel glob import: https://parceljs.org/features/dependency-resolution/#glob-specifiers
// vite.config.ts replaces this import by loading `character_icons_vite.ts` instead.
import images from "../../../assets/icons/*.webp";

import { css } from "@emotion/react";
import { characterIdWithoutNumber, getCharacter } from "botc/roles";

Expand Down
1 change: 1 addition & 0 deletions src/public/icons
1 change: 1 addition & 0 deletions src/public/manifest.webmanifest
1 change: 1 addition & 0 deletions src/public/screenshots
1 change: 1 addition & 0 deletions src/public/scripts.json
68 changes: 68 additions & 0 deletions vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import fs from "fs";
import path from "path";

import react from "@vitejs/plugin-react";
import posthtml from "posthtml";
import type {
AliasOptions,
IndexHtmlTransformHook,
IndexHtmlTransformResult,
} from "vite";
import { defineConfig } from "vite";

const alias: AliasOptions = [
// `.parcelrc` uses the `parcel-resolver-ts-base-url` plugin so imports can be relative to `./src/js` instead of the current file.
// The equivalent in Vite is to declare an alias for every file and directory in `./src/js`.
...fs.readdirSync("./src/js").map((filename) => {
const name = filename.replace(/\.(j|t)sx?$/, "");
return {
find: name,
replacement: path.resolve(__dirname, "src", "js", name),
};
}),
{
// Parcel imports our character icons using a Parcel-specific glob syntax.
// Redirect to character_icons_vite.ts, where we'll use a Vite-specific glob syntax instead.
find: /^.*\/assets\/icons\/\*\.webp$/,
replacement: path.resolve(__dirname, "src", "js", "character_icons_vite"),
},
];

// We run PostHTML on our `index.html` and `script.html` files to process an `<include>` tag.
function postHtmlPlugin() {
return {
name: "posthtml-transform",
async transformIndexHtml(html: string): Promise<IndexHtmlTransformResult> {
const postHtmlResult = await posthtml()
.use(require("posthtml-include")())
.process(html);
return postHtmlResult.html;
},
};
}

export default defineConfig({
assetsInclude: ["icons/touch-icon.png"],
build: {
emptyOutDir: true,
outDir: "../dist",
rollupOptions: {
input: {
main: path.resolve(__dirname, "src", "index.html"),
script: path.resolve(__dirname, "src", "script.html"),
},
},
},
plugins: [
react({
babel: {
babelrc: true,
},
}),
postHtmlPlugin(),
],
resolve: {
alias,
},
root: "src",
});
Loading
Loading