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

feat(dev): add BrowserMeta file for @remix-run/dev #6441

Closed
wants to merge 19 commits into from
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
1 change: 1 addition & 0 deletions contributors.yml
Original file line number Diff line number Diff line change
Expand Up @@ -540,3 +540,4 @@
- yudai-nkt
- baby230211
- TomVance
- 19Qingfeng
59 changes: 31 additions & 28 deletions packages/remix-dev/cli/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,8 @@ export async function init(
}
} catch (error: unknown) {
if (error instanceof Error) {
error.message = `${colors.error("🚨 Oops, remix.init failed")}\n\n${
error.message
}`;
error.message = `${colors.error("🚨 Oops, remix.init failed")}\n\n${error.message
}`;
}
throw error;
}
Expand All @@ -120,7 +119,7 @@ export async function setup(platformArg?: string) {
) {
console.warn(
`Using '${platformArg}' as a platform value is deprecated. Use ` +
"'cloudflare' instead."
"'cloudflare' instead."
);
console.log("HINT: check the `postinstall` script in `package.json`");
platform = SetupPlatform.Cloudflare;
Expand All @@ -147,7 +146,8 @@ export async function routes(
export async function build(
remixRoot: string,
modeArg?: string,
sourcemap: boolean = false
sourcemap: boolean = false,
metafile: boolean = false
): Promise<void> {
let mode = parseMode(modeArg) ?? "production";

Expand All @@ -159,9 +159,9 @@ export async function build(
);
console.warn(
"You have enabled source maps in production. This will make your " +
"server-side code visible to the public and is highly discouraged! If " +
"you insist, please ensure you are using environment variables for " +
"secrets and not hard-coding them into your source!"
"server-side code visible to the public and is highly discouraged! If " +
"you insist, please ensure you are using environment variables for " +
"secrets and not hard-coding them into your source!"
);
console.warn(
"⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️⚠️\n"
Expand All @@ -173,13 +173,13 @@ export async function build(
let options: Options = {
mode,
sourcemap,
metafile,
onWarning: warnOnce,
};
if (mode === "development" && config.future.unstable_dev) {
let origin = await resolveDevOrigin(config);
options.devOrigin = origin;
}

fse.emptyDirSync(config.assetsBuildDirectory);
await compiler.build({ config, options }).catch((thrown) => {
compiler.logThrown(thrown);
Expand All @@ -203,13 +203,14 @@ export async function watch(
: await readConfig(remixRootOrConfig);

devServer.liveReload(config);
return await new Promise(() => {});
return await new Promise(() => { });
}

export async function dev(
remixRoot: string,
flags: {
debug?: boolean;
metafile?: boolean

// unstable_dev
command?: string;
Expand All @@ -233,9 +234,11 @@ export async function dev(

let config = await readConfig(remixRoot);

config.metafile = !!(flags.metafile || config.metafile);

if (config.future.unstable_dev === false) {
await devServer.serve(config, flags.port);
return await new Promise(() => {});
return await new Promise(() => { });
}

await devServer_unstable.serve(config, await resolveDevServe(config, flags));
Expand All @@ -250,11 +253,11 @@ export async function codemod(
console.error(colors.red("Error: Missing codemod name"));
console.log(
"Usage: " +
colors.gray(
`remix codemod <${colors.arg("codemod")}> [${colors.arg(
"projectDir"
)}]`
)
colors.gray(
`remix codemod <${colors.arg("codemod")}> [${colors.arg(
"projectDir"
)}]`
)
);
process.exit(1);
}
Expand Down Expand Up @@ -338,10 +341,10 @@ export async function generateEntry(
let serverRuntime = deps["@remix-run/deno"]
? "deno"
: deps["@remix-run/cloudflare"]
? "cloudflare"
: deps["@remix-run/node"]
? "node"
: undefined;
? "cloudflare"
: deps["@remix-run/node"]
? "node"
: undefined;

if (!serverRuntime) {
let serverRuntimes = [
Expand Down Expand Up @@ -384,15 +387,15 @@ export async function generateEntry(

let contents = isServerEntry
? await createServerEntry(
config.rootDirectory,
config.appDirectory,
defaultEntryServer
)
config.rootDirectory,
config.appDirectory,
defaultEntryServer
)
: await createClientEntry(
config.rootDirectory,
config.appDirectory,
defaultEntryClient
);
config.rootDirectory,
config.appDirectory,
defaultEntryClient
);

let outputExtension = useTypeScript ? "tsx" : "jsx";
let outputEntry = `${entry}.${outputExtension}`;
Expand Down
85 changes: 44 additions & 41 deletions packages/remix-dev/cli/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,11 @@ ${colors.logoBlue("R")} ${colors.logoGreen("E")} ${colors.logoYellow(
--remix-version The version of Remix to use
\`build\` Options:
--sourcemap Generate source maps for production
--metafile Generate js metafile for production
\`dev\` Options:
--debug Attach Node.js inspector
--port, -p Choose the port from which to run your app
--metafile Generate js metafile

[unstable_dev]
--command, -c Command used to run your app server
Expand Down Expand Up @@ -173,6 +175,7 @@ export async function run(argv: string[] = process.argv.slice(2)) {
"--json": Boolean,
"--remix-version": String,
"--sourcemap": Boolean,
"--metafile": Boolean,
"--template": String,
"--token": String,
"--typescript": Boolean,
Expand Down Expand Up @@ -284,41 +287,41 @@ export async function run(argv: string[] = process.argv.slice(2)) {
let projectDir = projectPath
? path.resolve(process.cwd(), projectPath)
: await inquirer
.prompt<{ dir: string }>([
{
type: "input",
name: "dir",
message: "Where would you like to create your app?",
default: "./my-remix-app",
async validate(input) {
try {
await validateNewProjectPath(String(input));
return true;
} catch (error: unknown) {
if (error instanceof Error && error.message) {
return error.message;
}
throw error;
.prompt<{ dir: string }>([
{
type: "input",
name: "dir",
message: "Where would you like to create your app?",
default: "./my-remix-app",
async validate(input) {
try {
await validateNewProjectPath(String(input));
return true;
} catch (error: unknown) {
if (error instanceof Error && error.message) {
return error.message;
}
},
throw error;
}
},
])
.then(async (input) => {
let inputDir = input.dir.startsWith("~")
? input.dir.replace("~", os.homedir())
: input.dir;
if (path.isAbsolute(inputDir)) {
return inputDir;
}
return path.resolve(process.cwd(), inputDir);
})
.catch((error) => {
if (error.isTtyError) {
console.log(helpText);
return;
}
throw error;
});
},
])
.then(async (input) => {
let inputDir = input.dir.startsWith("~")
? input.dir.replace("~", os.homedir())
: input.dir;
if (path.isAbsolute(inputDir)) {
return inputDir;
}
return path.resolve(process.cwd(), inputDir);
})
.catch((error) => {
if (error.isTtyError) {
console.log(helpText);
return;
}
throw error;
});

if (!projectDir) {
console.log(helpText);
Expand Down Expand Up @@ -417,10 +420,10 @@ export async function run(argv: string[] = process.argv.slice(2)) {
console.warn(
colors.warning(
"🚨 Your terminal doesn't support interactivity; using default " +
"configuration.\n\n" +
"If you'd like to use different settings, try passing them " +
`as arguments. Run \`${packageManager} create remix@latest --help\` to see ` +
"available options."
"configuration.\n\n" +
"If you'd like to use different settings, try passing them " +
`as arguments. Run \`${packageManager} create remix@latest --help\` to see ` +
"available options."
)
);
return {
Expand Down Expand Up @@ -457,9 +460,9 @@ export async function run(argv: string[] = process.argv.slice(2)) {
console.log(
colors.warning(
"💿 You've opted out of installing dependencies so we won't run the " +
path.join("remix.init", "index.js") +
" script for you just yet. Once you've installed " +
`dependencies, you can run it manually with \`${npxInterop[packageManager]} remix init\``
path.join("remix.init", "index.js") +
" script for you just yet. Once you've installed " +
`dependencies, you can run it manually with \`${npxInterop[packageManager]} remix init\``
)
);
console.log();
Expand Down Expand Up @@ -494,7 +497,7 @@ export async function run(argv: string[] = process.argv.slice(2)) {
break;
case "build":
if (!process.env.NODE_ENV) process.env.NODE_ENV = "production";
await commands.build(input[1], process.env.NODE_ENV, flags.sourcemap);
await commands.build(input[1], process.env.NODE_ENV, flags.sourcemap, flags.metafile);
break;
case "watch":
if (!process.env.NODE_ENV) process.env.NODE_ENV = "development";
Expand Down
18 changes: 14 additions & 4 deletions packages/remix-dev/compiler/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import * as Channel from "../channel";
import type { Manifest } from "../manifest";
import { create as createManifest, write as writeManifest } from "./manifest";
import { err, ok } from "../result";
import { createBrowserMetaFile } from "./utils/analyzer";

type Compiler = {
compile: (options?: {
Expand All @@ -27,6 +28,7 @@ export let create = async (ctx: Context): Promise<Compiler> => {
manifest: undefined as unknown as Channel.Type<Manifest>,
};


let subcompiler = {
css: await CSS.createCompiler(ctx),
js: await JS.createCompiler(ctx, channels),
Expand All @@ -45,6 +47,7 @@ export let create = async (ctx: Context): Promise<Compiler> => {
]);
};


let compile = async (
options: { onManifest?: (manifest: Manifest) => void } = {}
) => {
Expand Down Expand Up @@ -83,10 +86,10 @@ export let create = async (ctx: Context): Promise<Compiler> => {
let cssBundleHref =
css.value.bundle &&
ctx.config.publicPath +
path.relative(
ctx.config.assetsBuildDirectory,
path.resolve(css.value.bundle.path)
);
path.relative(
ctx.config.assetsBuildDirectory,
path.resolve(css.value.bundle.path)
);
channels.cssBundleHref.ok(cssBundleHref);
if (css.value.bundle) {
writes.cssBundle = CSS.writeBundle(ctx, css.value.outputFiles);
Expand All @@ -97,6 +100,12 @@ export let create = async (ctx: Context): Promise<Compiler> => {
if (!js.ok) throw error ?? js.error;
let { metafile, hmr } = js.value;

// create browser metafile when ctx.config.metafil is true
if (ctx.config.metafile || ctx.options.metafile) {
await createBrowserMetaFile(ctx, 'js', metafile)
}


// artifacts/manifest
let manifest = await createManifest({
config: ctx.config,
Expand All @@ -114,6 +123,7 @@ export let create = async (ctx: Context): Promise<Compiler> => {
// artifacts/server
writes.server = Server.write(ctx.config, server.value);


await Promise.all(Object.values(writes));
return manifest;
};
Expand Down
1 change: 1 addition & 0 deletions packages/remix-dev/compiler/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ type Mode = "development" | "production" | "test";
export type Options = {
mode: Mode;
sourcemap: boolean;
metafile?: boolean;
onWarning?: (message: string, key: string) => void;

// TODO: required in v2
Expand Down
40 changes: 40 additions & 0 deletions packages/remix-dev/compiler/utils/analyzer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { resolve, normalize } from 'path'
import fs from 'fs-extra'
import type { Metafile } from 'esbuild';

import type { Context } from "../context";
import invariant from "../../invariant";


const genMetaFile = (name: string) => `${name}.json`

const getMetaPath = (target: string, filename: string) => normalize(resolve(target, filename));



/**
* Generate metafile for esbuild analyze
* @returns
*/
const createBrowserMetaFile = (ctx: Context, name: string, metafile: Metafile) => {
let { debugDirectory } = ctx.config

if (metafile) {

let metafileName = genMetaFile(name)

try {
let output = getMetaPath(debugDirectory, metafileName);
if (!fs.existsSync(debugDirectory)) {
fs.mkdirSync(debugDirectory)
}
return fs.writeFile(normalize(output), JSON.stringify(metafile));
} catch (e) {
invariant(e, `Failed to generate ${metafileName} in ${debugDirectory}.`);
}
}
}

export {
createBrowserMetaFile
}
Loading