Skip to content

Commit

Permalink
feat(vite): exclude modules within .server directories from client …
Browse files Browse the repository at this point in the history
…build

and vice versa for `.client` directories and server build
  • Loading branch information
pcattori committed Nov 27, 2023
1 parent dec4c2d commit a5621bb
Show file tree
Hide file tree
Showing 7 changed files with 156 additions and 6 deletions.
6 changes: 6 additions & 0 deletions .changeset/chatty-shrimps-sell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"integration-tests": minor
"@remix-run/dev": minor
---

Vite: exclude modules within `.server` directories from client build
2 changes: 0 additions & 2 deletions integration/helpers/vite-template/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@
"paths": {
"~/*": ["./app/*"]
},

// Remix takes care of building everything in `remix build`.
"noEmit": true
}
}
20 changes: 19 additions & 1 deletion integration/helpers/vite.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { spawn, type ChildProcess } from "node:child_process";
import { spawn, spawnSync, type ChildProcess } from "node:child_process";
import path from "node:path";
import type { Readable } from "node:stream";
import url from "node:url";
Expand Down Expand Up @@ -119,6 +119,24 @@ const createDev =
return async () => await kill(proc.pid!);
};

export const viteBuild = (args: { cwd: string }) => {
let vite = resolveBin.sync("vite");
let commands = [
[vite, "build"],
[vite, "build", "--ssr"],
];
let results = [];
for (let command of commands) {
let result = spawnSync("node", command, {
cwd: args.cwd,
env: {
...process.env,
},
});
results.push(result);
}
return results;
};
export const viteDev = createDev([resolveBin.sync("vite"), "dev"]);
export const customDev = createDev(["./server.mjs"]);

Expand Down
3 changes: 2 additions & 1 deletion integration/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"strip-indent": "^3.0.0",
"tailwindcss": "^3.3.0",
"type-fest": "^4.0.0",
"typescript": "^5.1.0"
"typescript": "^5.1.0",
"vite-tsconfig-paths": "^4.2.1"
}
}
105 changes: 105 additions & 0 deletions integration/vite-dot-server-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import * as path from "node:path";
import { test, expect } from "@playwright/test";
import shell from "shelljs";
import glob from "glob";

import { createProject, viteBuild } from "./helpers/vite.js";

let files = {
"app/utils.server.ts": String.raw`
export const dotServerFile = "SERVER_ONLY_FILE";
`,
"app/.server/utils.ts": String.raw`
export const dotServerDir = "SERVER_ONLY_DIR";
`,
};

test("Vite / build / .server file in client fails with expected error", async () => {
let cwd = await createProject({
...files,
"app/routes/fail-server-file-in-client.tsx": String.raw`
import { dotServerFile } from "~/utils.server";
export default function() {
console.log(dotServerFile);
return <h1>Fail: Server file included in client</h1>
}
`,
});
let client = viteBuild({ cwd })[0];
let stderr = client.stderr.toString("utf8");
expect(stderr).toMatch(
`"dotServerFile" is not exported by "app/utils.server.ts"`
);
});

test("Vite / build / .server dir in client fails with expected error", async () => {
let cwd = await createProject({
...files,
"app/routes/fail-server-dir-in-client.tsx": String.raw`
import { dotServerDir } from "~/.server/utils";
export default function() {
console.log(dotServerDir);
return <h1>Fail: Server directory included in client</h1>
}
`,
});
let client = viteBuild({ cwd })[0];
let stderr = client.stderr.toString("utf8");
expect(stderr).toMatch(
`"dotServerDir" is not exported by "app/.server/utils.ts"`
);
});

test("Vite / build / dead-code elimination for server exports", async () => {
let cwd = await createProject({
...files,
"app/routes/remove-server-exports-and-dce.tsx": String.raw`
import fs from "node:fs";
import { json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
import { dotServerFile } from "../utils.server";
import { dotServerDir } from "../.server/utils";
export const loader = () => {
let contents = fs.readFileSync("blah");
let data = dotServerFile + dotServerDir + serverOnly + contents;
return json({ data });
}
export const action = () => {
console.log(dotServerFile, dotServerDir, serverOnly);
return null;
}
export default function() {
let { data } = useLoaderData<typeof loader>();
return (
<>
<h2>Index</h2>
<p>{data}</p>
</>
);
}
`,
});
let client = viteBuild({ cwd })[0];
expect(client.status).toBe(0);

// detect client asset files
let assetFiles = glob.sync("**/*.@(js|jsx|ts|tsx)", {
cwd: path.join(cwd, "build/client"),
absolute: true,
});

// grep for server-only values in client assets
let result = shell
.grep("-l", /SERVER_ONLY_FILE|SERVER_ONLY_DIR|node:fs/, assetFiles)
.stdout.trim()
.split("\n")
.filter((line) => line.length > 0);

expect(result).toHaveLength(0);
});
12 changes: 10 additions & 2 deletions packages/remix-dev/vite/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -889,22 +889,30 @@ export const remixVitePlugin: RemixVitePlugin = (options = {}) => {
name: "remix-empty-server-modules",
enforce: "pre",
async transform(_code, id, options) {
if (!options?.ssr && /\.server(\.[cm]?[jt]sx?)?$/.test(id))
if (options?.ssr) return;
let serverFileRE = /\.server(\.[cm]?[jt]sx?)?$/;
let serverDirRE = /\/\.server\//;
if (serverFileRE.test(id) || serverDirRE.test(id)) {
return {
code: "export default {}",
map: null,
};
}
},
},
{
name: "remix-empty-client-modules",
enforce: "pre",
async transform(_code, id, options) {
if (options?.ssr && /\.client(\.[cm]?[jt]sx?)?$/.test(id))
if (!options?.ssr) return;
let clientFileRE = /\.client(\.[cm]?[jt]sx?)?$/;
let clientDirRE = /\/\.client\//;
if (clientFileRE.test(id) || clientDirRE.test(id)) {
return {
code: "export default {}",
map: null,
};
}
},
},
{
Expand Down
14 changes: 14 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -12553,6 +12553,11 @@ ts-interface-checker@^0.1.9:
resolved "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699"
integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==

tsconfck@^2.1.0:
version "2.1.2"
resolved "https://registry.npmjs.org/tsconfck/-/tsconfck-2.1.2.tgz#f667035874fa41d908c1fe4d765345fcb1df6e35"
integrity sha512-ghqN1b0puy3MhhviwO2kGF8SeMDNhEbnKxjK7h6+fvY9JAxqvXi8y5NAHSQv687OVboS2uZIByzGd45/YxrRHg==

tsconfig-paths@^3.14.1:
version "3.14.1"
resolved "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz"
Expand Down Expand Up @@ -13122,6 +13127,15 @@ vite-node@^0.28.5:
source-map-support "^0.5.21"
vite "^3.0.0 || ^4.0.0"

vite-tsconfig-paths@^4.2.1:
version "4.2.1"
resolved "https://registry.npmjs.org/vite-tsconfig-paths/-/vite-tsconfig-paths-4.2.1.tgz#e53b89096b91d31a6d1e26f75999ea8c336a89ed"
integrity sha512-GNUI6ZgPqT3oervkvzU+qtys83+75N/OuDaQl7HmOqFTb0pjZsuARrRipsyJhJ3enqV8beI1xhGbToR4o78nSQ==
dependencies:
debug "^4.1.1"
globrex "^0.1.2"
tsconfck "^2.1.0"

"vite@^3.0.0 || ^4.0.0", vite@^4.1.4:
version "4.4.10"
resolved "https://registry.npmjs.org/vite/-/vite-4.4.10.tgz#3794639cc433f7cb33ad286930bf0378c86261c8"
Expand Down

0 comments on commit a5621bb

Please sign in to comment.