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

Remix rspack #3793

Open
wants to merge 73 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
532ebae
remix
Nov 7, 2023
f2ac460
WUO: add remix example
Nov 7, 2023
1b5811d
WUO: add remix example
Nov 7, 2023
53cadc4
WIP: implement full loading chain
Nov 9, 2023
ad42e8c
WIP: Remix Rspack
Nov 10, 2023
e9392f9
WIP: Remix Rspack
Nov 10, 2023
4d6de8f
WIP: Remix Rspack
Nov 13, 2023
fa057f8
update lock
Nov 13, 2023
3f0b436
update lock
Nov 13, 2023
2fca8d4
Update _index.tsx
ScriptedAlchemy Nov 9, 2023
50086e4
chore(deps): update dependency @modern-js-app/eslint-config to v2.40.0
renovate[bot] Nov 13, 2023
b8086cc
rename package conflicts
ScriptedAlchemy Nov 13, 2023
f3ab926
update lock
Nov 13, 2023
fd69f05
fix package running
ScriptedAlchemy Nov 13, 2023
e801e71
fix remix example
ScriptedAlchemy Nov 13, 2023
01f51d3
remix
Nov 7, 2023
3c96437
WUO: add remix example
Nov 7, 2023
5912100
WUO: add remix example
Nov 7, 2023
d8309ef
WIP: implement full loading chain
Nov 9, 2023
013643e
WIP: Remix Rspack
Nov 10, 2023
ce93355
WIP: Remix Rspack
Nov 10, 2023
63b1edd
WIP: Remix Rspack
Nov 13, 2023
b4fcf1a
update lock
Nov 13, 2023
5356699
Update _index.tsx
ScriptedAlchemy Nov 9, 2023
aea4245
rename package conflicts
ScriptedAlchemy Nov 13, 2023
05cd0b8
update lock
Nov 13, 2023
020fb44
fix package running
ScriptedAlchemy Nov 13, 2023
1b82294
fix remix example
ScriptedAlchemy Nov 13, 2023
7c36fce
fix remix example
ScriptedAlchemy Nov 14, 2023
917ba0d
Update dependency jsdom to v21.1.2
ScriptedAlchemy Nov 14, 2023
b970e2c
fix remix example
ScriptedAlchemy Nov 14, 2023
ee1af57
Update dependency karma-coverage to v2.2.1
ScriptedAlchemy Nov 14, 2023
92b9de8
fix remix example
ScriptedAlchemy Nov 14, 2023
f1bf9e4
Update dependency svelte-loader to v3.1.9
ScriptedAlchemy Nov 14, 2023
56ff1a6
Update dependency style-loader to v3.3.3
ScriptedAlchemy Nov 14, 2023
fa937ff
Update dependency rollup to v2.79.1
ScriptedAlchemy Nov 14, 2023
2e6cb75
chore(deps): update dependency node to v16.20.2
renovate[bot] Nov 14, 2023
9e63fdd
chore(deps): update dependency postcss-preset-env to ^9.3.0
renovate[bot] Nov 14, 2023
b6f371b
fix remix example
ScriptedAlchemy Nov 14, 2023
bad9415
Merge remote-tracking branch 'origin/remix-rspack' into remix-rspack
Nov 14, 2023
1ae9fc0
remix
Nov 7, 2023
9087012
WUO: add remix example
Nov 7, 2023
eca28fb
WUO: add remix example
Nov 7, 2023
576a1ef
WIP: implement full loading chain
Nov 9, 2023
f66d8e1
Update _index.tsx
ScriptedAlchemy Nov 9, 2023
ebad34a
rename package conflicts
ScriptedAlchemy Nov 13, 2023
6d3c273
WIP: Remix Rspack
Nov 10, 2023
613761a
WIP: Remix Rspack
Nov 10, 2023
a68b445
WIP: Remix Rspack
Nov 13, 2023
3aa0af6
update lock
Nov 13, 2023
7c6c2ed
rename package conflicts
ScriptedAlchemy Nov 13, 2023
f24b3bf
update lock
Nov 13, 2023
5111673
fix remix example
ScriptedAlchemy Nov 13, 2023
cb3f2c7
fix remix example
ScriptedAlchemy Nov 14, 2023
55ce9c0
fix remix example
ScriptedAlchemy Nov 14, 2023
895f361
Update dependency svelte-loader to v3.1.9
ScriptedAlchemy Nov 14, 2023
1ce9e93
Update dependency rollup to v2.79.1
ScriptedAlchemy Nov 14, 2023
20784f7
fix remix example
ScriptedAlchemy Nov 14, 2023
bbf17b9
rspack example
ScriptedAlchemy Nov 14, 2023
2e358ac
update locks
ScriptedAlchemy Nov 14, 2023
ee28e1f
abstract build stuff
ScriptedAlchemy Nov 14, 2023
4e97fe8
abstract build stuff
ScriptedAlchemy Nov 14, 2023
53315e1
lock file update
ScriptedAlchemy Nov 14, 2023
db16031
fix stuff
ScriptedAlchemy Nov 14, 2023
c1a2d4f
fix stuff
ScriptedAlchemy Nov 14, 2023
43a2d0b
fix stuff
ScriptedAlchemy Nov 15, 2023
5836773
fix stuff
ScriptedAlchemy Nov 15, 2023
35468af
Merge remote-tracking branch 'origin/remix-rspack' into remix-rspack
Nov 16, 2023
db0523b
fix stuff
ScriptedAlchemy Nov 16, 2023
b3031ef
Merge remote-tracking branch 'origin/remix-rspack' into remix-rspack
Nov 17, 2023
1b1a3c0
update lock
Jan 3, 2024
a09ca49
Merge branch 'master' into remix-rspack
Apr 1, 2024
80b3772
update rspack remix example
Apr 1, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4,312 changes: 3,297 additions & 1,015 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions remix-rspack/app1/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.DS_Store
.cache
node_modules
build
public/build
29 changes: 29 additions & 0 deletions remix-rspack/app1/app/root.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {
Links,
Meta,
Outlet,
Scripts,
ScrollRestoration,
} from "@remix-run/react";

export function loader() {
return "Hello, World!";
}

export default function App() {
return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<Meta />
<Links />
</head>
<body>
<Outlet />
<ScrollRestoration />
<Scripts />
</body>
</html>
);
}
14 changes: 14 additions & 0 deletions remix-rspack/app1/app/routes/_index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { useLoaderData } from "@remix-run/react";
export function loader() {
return { message: "Hello, World!" };
}
// const Button = lazy(() => import('app2/button'));
export default function Home() {
const { message } = useLoaderData();
return (
<div>
<h1>Home</h1>
<p>{message}</p>
</div>
);
}
3 changes: 3 additions & 0 deletions remix-rspack/app1/components/Button.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default () => {
return <button>Federated Button from App1</button>
}
37 changes: 37 additions & 0 deletions remix-rspack/app1/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"name": "rspack-remix-app1",
"version": "0.0.0",
"type": "module",
"scripts": {
"build:browser": "rspack --mode=development --config webpack.browser.js",
"build:server": "rspack --mode=development --config webpack.server.js",
"start": "rm -rf ./public/build; pnpm run build:browser && pnpm run build:server && node ./build/index.js",
"server": "node ./build/index.js"
},
"author": "Jacob Ebey",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.23.3",
"@remix-run/dev": "^2.2.0",
"@rspack/cli": "^0.3.12",
"@rspack/core": "^0.3.12",
"@types/express": "^4.17.21",
"@types/react": "^18.2.37",
"@types/react-dom": "^18.2.15",
"babel-loader": "^9.1.3",
"babel-plugin-eliminator": "^1.0.1",
"esbuild": "^0.19.5",
"esbuild-loader": "^4.0.2",
"webpack-node-externals": "^3.0.0"
},
"dependencies": {
"@remix-run/express": "^2.2.0",
"@remix-run/node": "^2.2.0",
"@remix-run/react": "^2.2.0",
"cors": "2.8.5",
"express": "^4.18.2",
"isbot": "^3.7.0",
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
}
75 changes: 75 additions & 0 deletions remix-rspack/app1/remix-parts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import * as path from "node:path";

/**
*
* @param {import("@remix-run/dev").ResolvedRemixConfig} config
* @param {import("@remix-run/dev").AssetsManifest} manifest
* @returns
*/
export function createServerBuildEntry(config, manifest) {
const routeImports = Object.values(config.routes).map((route, index) => {
return `import * as route${index} from "${path
.relative(
path.resolve("./.cache"),
path.resolve(config.appDirectory, route.file)
)
.replace(/\\/g, "/")}";`;
});
const routes = Object.entries(config.routes).map(
([routeId, route], index) => {
return `${JSON.stringify(routeId)}: {
id: ${JSON.stringify(route.id)},
parentId: ${JSON.stringify(route.parentId)},
path: ${JSON.stringify(route.path)},
index: ${JSON.stringify(route.index)},
caseSensitive: ${JSON.stringify(route.caseSensitive)},
module: route${index}
}`;
}
);

return `
import * as entryServer from "${config.entryServerFilePath.replace(
/\\/g,
"/"
)}";
${routeImports.join("\n")}
export const entry = { module: entryServer };
export const routes = {
${routes.join(",\n ")}
};
export const assets = ${JSON.stringify(manifest)};
export const future = ${JSON.stringify(config.future)};
export const publicPath = ${JSON.stringify(config.publicPath)};
`;
}
export class HoistContainerReferences {
apply(compiler) {
compiler.hooks.thisCompilation.tap('stuff', (compilation) => {
compilation.hooks.afterOptimizeChunks.tap(
'EmbeddedContainerPlugin',
(chunks) => {
const chunkSet = new Map()
const externalRequests = new Set()
for (const chunk of chunks) {
chunkSet.set(chunk.id || chunk.name, chunk)
}
// console.log(chunkSet)
for (const chunk of chunks) {
const remoteModules = compilation.chunkGraph.getChunkModulesIterableBySourceType(chunk,'remote');
if(!remoteModules) continue
for (const remoteModule of remoteModules) {
remoteModule.dependencies.forEach((dep) => {
const mod = compilation.moduleGraph.getModule(dep)
externalRequests.add(mod);
const runtimeChunk = chunkSet.get(chunk.runtime)
compilation.chunkGraph.connectChunkAndModule(runtimeChunk, mod)
})
}
}
console.log(externalRequests);
}
);
})
}
}
5 changes: 5 additions & 0 deletions remix-rspack/app1/remix.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/** @type {import("@remix-run/dev").AppConfig} */
export default {
server: "server.ts",
serverModuleFormat: 'commonjs'
};
15 changes: 15 additions & 0 deletions remix-rspack/app1/server.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import express from "express";
import { createRequestHandler } from "@remix-run/express";
import cors from 'cors';

import * as build from "@remix-run/dev/server-build.js";

const app = express();
app.use(cors());
app.use(express.static("public"));
app.use('/server', express.static("build"));
app.all("*", createRequestHandler({ build }));

app.listen(3000, () => {
console.log(`Server started at http://localhost:3000`);
});
8 changes: 8 additions & 0 deletions remix-rspack/app1/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"compilerOptions": {
"module": "Node16",
"moduleResolution": "Node16",
"strict": true,
"jsx": "react-jsx"
}
}
25 changes: 25 additions & 0 deletions remix-rspack/app1/utils/get-exports.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import os from "os";
import esbuild from "esbuild";

export function getExports(routePath, remixConfig) {
const { metafile, errors } = esbuild.buildSync({
sourceRoot: remixConfig.appDirectory,
entryPoints: [routePath],
target: "esnext",
bundle: false,
metafile: true,
write: false,
outdir: os.tmpdir(),
});
if ((errors === null || errors === void 0 ? void 0 : errors.length) > 0) {
throw new Error(
esbuild.formatMessagesSync(errors, { kind: "error" }).join("\n")
);
}
const outputs = Object.values(metafile.outputs);
if (outputs.length !== 1) {
throw Error();
}
const output = outputs[0];
return output.exports;
}
142 changes: 142 additions & 0 deletions remix-rspack/app1/utils/manifest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
import * as fs from "node:fs";
import * as path from "node:path";

import { getExports } from "./get-exports.js";

function createUrl(publicPath, file) {
return (
publicPath.split(path.win32.sep).join("/") +
(file || "").split(path.win32.sep).join("/")
);
}

/**
*
* @param {import("webpack").StatsCompilation} stats
* @param {string} publicPath
* @returns {(group: string) => string[]}
*/
function createNamedChunkGroupFactory(stats, publicPath) {
const chunksById = new Map(stats.chunks?.map((chunk) => [chunk.id, chunk]));
return (group) => {
/** @type {Set<string>} */
const files = new Set();
stats.namedChunkGroups?.[group].chunks?.forEach((chunkId) => {
const chunk = chunksById.get(chunkId);
chunk?.files?.forEach((file) => files.add(createUrl(publicPath, file)));
});
return [...files];
};
}

/**
* @param {webpack.StatsCompilation} param0
* @param {string} entrypointId
*/
const getAssets = ({ entrypoints }, entrypointId) => {
if (entrypoints === undefined) throw Error("todo");
const { assets } = entrypoints[entrypointId];
if (assets === undefined) throw Error("todo");
return assets;
};

/**
* @param {import("@remix-run/dev").ResolvedRemixConfig} remixConfig
* @param {import("webpack").Stats} stats
* @returns {import("@remix-run/dev").AssetsManifest}
*/
export async function toManifest(remixConfig, stats) {
const compilationStats = stats.toJson({
modules: true,
entrypoints: true,
assets: true,
groupAssetsByChunk: true,
hash: true,
});
const getByNamedChunkGroup = createNamedChunkGroupFactory(
compilationStats,
remixConfig.publicPath
);

const entryImports = getByNamedChunkGroup("entry.client");
const entryModule = createUrl(
remixConfig.publicPath,
getAssets(compilationStats, "entry.client").slice(-1)[0].name
);
const rootImports = getByNamedChunkGroup("root");

// TODO: what are runtime imports? dynamic imports?
// let runtimeImports = compilationStats.assetsByChunkName["runtime"].map(
// (asset) => createUrl(remixConfig.publicPath, asset)
// );

const routes = Object.fromEntries(
Object.entries(remixConfig.routes).map(([routeId, route]) => {
const assets = getAssets(compilationStats, routeId);
const routeImports = assets
.slice(0, -1)
.map((asset) => createUrl(remixConfig.publicPath, asset.name));
const routeModule = createUrl(
remixConfig.publicPath,
assets.slice(-1)[0].name
);
const routePath = path.resolve(remixConfig.appDirectory, route.file);
const routeExports = getExports(routePath, remixConfig);
return [
routeId,
{
id: route.id,
parentId: route.parentId,
path: route.path,
index: route.index,
caseSensitive: route.caseSensitive,
module: routeModule,
imports: routeImports,
hasAction: routeExports.includes("action"),
hasLoader: routeExports.includes("loader"),
hasCatchBoundary: routeExports.includes("CatchBoundary"),
hasErrorBoundary: routeExports.includes("ErrorBoundary"),
},
];
})
);

const version = compilationStats.hash;
if (version === undefined) throw Error("todo");
return {
version,
url: createUrl(
remixConfig.publicPath,
`manifest-${version.toUpperCase()}.js`
),
entry: {
imports: [
...new Set([/* ...runtimeImports, */ ...entryImports, ...rootImports]),
],
module: entryModule,
},
routes,
};
}

export function writeManifest(config, manifest) {
fs.mkdirSync("./.cache", { recursive: true });
fs.writeFileSync(
"./.cache/manifest.json",
JSON.stringify(manifest, null, 2),
"utf8"
);

fs.mkdirSync(config.assetsBuildDirectory, { recursive: true });
fs.writeFileSync(
path.resolve(config.assetsBuildDirectory, path.basename(manifest.url)),
`window.__remixManifest=${JSON.stringify(manifest)};`
);
}

/**
* @returns {import("@remix-run/dev").AssetsManifest}
*/
export function getManifest() {
return JSON.parse(fs.readFileSync("./.cache/manifest.json", "utf8"));
}