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: environment variables #321

Merged
merged 15 commits into from
Jan 1, 2024
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- breaking: no index html #289
- fix(vercel): option for static build #310
- feat(router): createPages #293
- feat: environment variables #321

## [0.18.1] - 2023-12-15
### Changed
Expand Down
2 changes: 1 addition & 1 deletion e2e/fixtures/ssr-basic/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const rootElement = (
</StrictMode>
);

if ((globalThis as any).__WAKU_SSR_ENABLED__) {
if (import.meta.env.WAKU_HYDRATE) {
hydrateRoot(document.body, rootElement);
} else {
createRoot(document.body).render(rootElement);
Expand Down
2 changes: 1 addition & 1 deletion examples/01_counter/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const rootElement = (
</StrictMode>
);

if ((globalThis as any).__WAKU_SSR_ENABLED__) {
if (import.meta.env.WAKU_HYDRATE) {
hydrateRoot(document.body, rootElement);
} else {
createRoot(document.body).render(rootElement);
Expand Down
2 changes: 1 addition & 1 deletion examples/02_async/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const rootElement = (
</StrictMode>
);

if ((globalThis as any).__WAKU_SSR_ENABLED__) {
if (import.meta.env.WAKU_HYDRATE) {
hydrateRoot(document.body, rootElement);
} else {
createRoot(document.body).render(rootElement);
Expand Down
2 changes: 1 addition & 1 deletion examples/03_promise/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const rootElement = (
</StrictMode>
);

if ((globalThis as any).__WAKU_SSR_ENABLED__) {
if (import.meta.env.WAKU_HYDRATE) {
hydrateRoot(document.body, rootElement);
} else {
createRoot(document.body).render(rootElement);
Expand Down
2 changes: 1 addition & 1 deletion examples/04_callserver/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const rootElement = (
</StrictMode>
);

if ((globalThis as any).__WAKU_SSR_ENABLED__) {
if (import.meta.env.WAKU_HYDRATE) {
hydrateRoot(document.body, rootElement);
} else {
createRoot(document.body).render(rootElement);
Expand Down
2 changes: 1 addition & 1 deletion examples/05_mutation/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const rootElement = (
</StrictMode>
);

if ((globalThis as any).__WAKU_SSR_ENABLED__) {
if (import.meta.env.WAKU_HYDRATE) {
hydrateRoot(document.body, rootElement);
} else {
createRoot(document.body).render(rootElement);
Expand Down
2 changes: 1 addition & 1 deletion examples/06_nesting/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const rootElement = (
</StrictMode>
);

if ((globalThis as any).__WAKU_SSR_ENABLED__) {
if (import.meta.env.WAKU_HYDRATE) {
hydrateRoot(document.body, rootElement);
} else {
createRoot(document.body).render(rootElement);
Expand Down
2 changes: 1 addition & 1 deletion examples/07_router/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const rootElement = (
</StrictMode>
);

if ((globalThis as any).__WAKU_SSR_ENABLED__) {
if (import.meta.env.WAKU_HYDRATE) {
hydrateRoot(document.body, rootElement);
} else {
createRoot(document.body).render(rootElement);
Expand Down
2 changes: 1 addition & 1 deletion examples/08_cookies/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const rootElement = (
</StrictMode>
);

if ((globalThis as any).__WAKU_SSR_ENABLED__) {
if (import.meta.env.WAKU_HYDRATE) {
hydrateRoot(document.body, rootElement);
} else {
createRoot(document.body).render(rootElement);
Expand Down
1 change: 1 addition & 0 deletions examples/09_cssmodules/.env.local
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
WAKU_PUBLIC_HELLO="Hello from env file"
1 change: 1 addition & 0 deletions examples/09_cssmodules/src/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const App = ({ name }: { name: string }) => {
<h1 className={styles.title}>Hello {name}!!</h1>
<h3>This is a server component.</h3>
<Counter />
Env: {import.meta.env.WAKU_PUBLIC_HELLO}
</div>
);
};
Expand Down
1 change: 1 addition & 0 deletions examples/09_cssmodules/src/components/Counter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export const Counter = () => {
<p>Count: {count}</p>
<button onClick={() => setCount((c) => c + 1)}>Increment</button>
<h3>This is a client component.</h3>
Env: {import.meta.env.WAKU_PUBLIC_HELLO}
</div>
);
};
2 changes: 1 addition & 1 deletion examples/09_cssmodules/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const rootElement = (
</StrictMode>
);

if ((globalThis as any).__WAKU_SSR_ENABLED__) {
if (import.meta.env.WAKU_HYDRATE) {
hydrateRoot(document.body, rootElement);
} else {
createRoot(document.body).render(rootElement);
Expand Down
2 changes: 1 addition & 1 deletion examples/10_dynamicroute/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const rootElement = (
</StrictMode>
);

if ((globalThis as any).__WAKU_SSR_ENABLED__) {
if (import.meta.env.WAKU_HYDRATE) {
hydrateRoot(document.body, rootElement);
} else {
createRoot(document.body).render(rootElement);
Expand Down
2 changes: 1 addition & 1 deletion examples/11_form/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const rootElement = (
</StrictMode>
);

if ((globalThis as any).__WAKU_SSR_ENABLED__) {
if (import.meta.env.WAKU_HYDRATE) {
hydrateRoot(document.body, rootElement);
} else {
createRoot(document.body).render(rootElement);
Expand Down
2 changes: 1 addition & 1 deletion examples/12_css/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const rootElement = (
</StrictMode>
);

if ((globalThis as any).__WAKU_SSR_ENABLED__) {
if (import.meta.env.WAKU_HYDRATE) {
hydrateRoot(document.body, rootElement);
} else {
createRoot(document.body).render(rootElement);
Expand Down
29 changes: 26 additions & 3 deletions packages/waku/src/cli.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env node

import path from 'node:path';
import { existsSync, readFileSync } from 'node:fs';
import { pathToFileURL } from 'node:url';
import { parseArgs } from 'node:util';
import { createRequire } from 'node:module';
Expand Down Expand Up @@ -77,14 +78,15 @@ if (values.version) {

async function runDev(options: { ssr: boolean }) {
const app = new Hono();
app.use('*', honoDevMiddleware(options));
app.use('*', honoDevMiddleware({ ...options, env: loadEnv() }));
const port = parseInt(process.env.PORT || '3000', 10);
startServer(app, port);
}

async function runBuild(options: { ssr: boolean }) {
await build({
ssr: options.ssr,
...options,
env: loadEnv(),
vercel:
values['with-vercel'] ?? !!process.env.VERCEL
? {
Expand All @@ -102,7 +104,7 @@ async function runStart(options: { ssr: boolean }) {
pathToFileURL(path.resolve(distDir, entriesJs)).toString()
);
const app = new Hono();
app.use('*', honoPrdMiddleware({ entries, ...options }));
app.use('*', honoPrdMiddleware({ ...options, entries, env: loadEnv() }));
app.use('*', serveStatic({ root: path.join(distDir, publicDir) }));
const port = parseInt(process.env.PORT || '8080', 10);
startServer(app, port);
Expand Down Expand Up @@ -140,3 +142,24 @@ Options:
-h, --help Display this help message
`);
}

function loadEnv() {
const env: Record<string, string> = {
...(process.env as Record<string, string>),
};
if (existsSync('.env.local')) {
for (const line of readFileSync('.env.local', 'utf8').split('\n')) {
const [key, value] = line.split('=');
if (key && value) {
if (value.startsWith('"') && value.endsWith('"')) {
env[key.trim()] = value.slice(1, -1);
} else if (value.startsWith("'") && value.endsWith("'")) {
env[key.trim()] = value.slice(1, -1);
} else {
env[key.trim()] = value.trim();
}
}
}
}
return env;
}
27 changes: 15 additions & 12 deletions packages/waku/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,20 @@ import {
} from 'react';
import type { ReactNode } from 'react';
import RSDWClient from 'react-server-dom-webpack/client';

import { encodeInput } from './lib/renderers/utils.js';

const { createFromFetch, encodeReply } = RSDWClient;

declare global {
interface ImportMeta {
readonly env: Record<string, string>;
}
}

const BASE_PATH = `${import.meta.env?.WAKU_CONFIG_BASE_PATH}${import.meta.env
?.WAKU_CONFIG_RSC_PATH}/`;

const checkStatus = async (
responsePromise: Promise<Response>,
): Promise<Response> => {
Expand All @@ -39,19 +49,16 @@ const mergeElements = cache(
},
);

// TODO get basePath from config

export const fetchRSC = cache(
(
input: string,
searchParamsString: string,
rerender: (fn: (prev: Elements) => Elements) => void,
basePath = '/RSC/',
): Elements => {
const options = {
async callServer(actionId: string, args: unknown[]) {
const response = fetch(
basePath + encodeInput(encodeURIComponent(actionId)),
BASE_PATH + encodeInput(encodeURIComponent(actionId)),
{
method: 'POST',
body: await encodeReply(args),
Expand All @@ -70,7 +77,7 @@ export const fetchRSC = cache(
};
const prefetched = ((globalThis as any).__WAKU_PREFETCHED__ ||= {});
const url =
basePath +
BASE_PATH +
encodeInput(input) +
(searchParamsString ? '?' + searchParamsString : '');
const response = prefetched[url] || fetch(url);
Expand All @@ -84,10 +91,10 @@ export const fetchRSC = cache(
);

export const prefetchRSC = cache(
(input: string, searchParamsString: string, basePath = '/RSC/'): void => {
(input: string, searchParamsString: string): void => {
const prefetched = ((globalThis as any).__WAKU_PREFETCHED__ ||= {});
const url =
basePath +
BASE_PATH +
encodeInput(input) +
(searchParamsString ? '?' + searchParamsString : '');
if (!(url in prefetched)) {
Expand Down Expand Up @@ -120,20 +127,17 @@ export const Root = ({
initialInput,
initialSearchParamsString,
children,
basePath,
}: {
initialInput?: string;
initialSearchParamsString?: string;
children: ReactNode;
basePath?: string;
}) => {
const [getRerender, setRerender] = createRerender();
const [elements, setElements] = useState(() =>
fetchRSC(
initialInput || '',
initialSearchParamsString || '',
getRerender(),
basePath,
),
);
setRerender(setElements);
Expand All @@ -143,11 +147,10 @@ export const Root = ({
input,
searchParams?.toString() || '',
getRerender(),
basePath,
);
setElements((prev) => mergeElements(prev, data));
},
[getRerender, basePath],
[getRerender],
);
return createElement(
RefetchContext.Provider,
Expand Down
21 changes: 14 additions & 7 deletions packages/waku/src/lib/builder/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import { rscIndexPlugin } from '../plugins/vite-plugin-rsc-index.js';
import { rscAnalyzePlugin } from '../plugins/vite-plugin-rsc-analyze.js';
import { nonjsResolvePlugin } from '../plugins/vite-plugin-nonjs-resolve.js';
import { rscTransformPlugin } from '../plugins/vite-plugin-rsc-transform.js';
import { rscEnvPlugin } from '../plugins/vite-plugin-rsc-env.js';
import { patchReactRefresh } from '../plugins/patch-react-refresh.js';
import { emitVercelOutput } from './output-vercel.js';
import { emitCloudflareOutput } from './output-cloudflare.js';
Expand Down Expand Up @@ -158,6 +159,7 @@ const buildServerBundle = async (
},
serverEntryFiles,
}),
rscEnvPlugin({ config }),
],
ssr: {
resolve: {
Expand Down Expand Up @@ -248,6 +250,7 @@ const buildClientBundle = async (
commonEntryFiles: Record<string, string>,
clientEntryFiles: Record<string, string>,
serverBuildOutput: Awaited<ReturnType<typeof buildServerBundle>>,
ssr: boolean,
) => {
const mainJsFile = joinPath(rootDir, config.srcDir, config.mainJs);
const cssAssets = serverBuildOutput.output.flatMap(({ type, fileName }) =>
Expand All @@ -258,6 +261,7 @@ const buildClientBundle = async (
plugins: [
patchReactRefresh(viteReact()),
rscIndexPlugin({ ...config, cssAssets }),
rscEnvPlugin({ config, hydrate: ssr }),
],
build: {
outDir: joinPath(rootDir, config.distDir, config.publicDir),
Expand Down Expand Up @@ -492,10 +496,12 @@ const resolveFileName = (fname: string) => {
export async function build(options: {
config?: Config;
ssr?: boolean;
env?: Record<string, string>;
vercel?: { type: 'static' | 'serverless' } | undefined;
cloudflare?: boolean;
deno?: boolean;
}) {
(globalThis as any).__WAKU_PRIVATE_ENV__ = options.env || {};
const config = await resolveConfig(options.config || {});
const rootDir = (
await resolveViteConfig({}, 'build', 'production', 'production')
Expand Down Expand Up @@ -524,6 +530,7 @@ export async function build(options: {
commonEntryFiles,
clientEntryFiles,
serverBuildOutput,
!!options.ssr,
);

const { buildConfig, getClientModules, rscFiles } = await emitRscFiles(
Expand All @@ -537,25 +544,25 @@ export async function build(options: {
distEntriesFile,
buildConfig,
getClientModules,
!!options?.ssr,
!!options.ssr,
);

if (options?.vercel) {
if (options.vercel) {
await emitVercelOutput(
rootDir,
config,
rscFiles,
htmlFiles,
!!options?.ssr,
!!options.ssr,
options.vercel.type,
);
}

if (options?.cloudflare) {
await emitCloudflareOutput(rootDir, config, !!options?.ssr);
if (options.cloudflare) {
await emitCloudflareOutput(rootDir, config, !!options.ssr);
}

if (options?.deno) {
await emitDenoOutput(rootDir, config, !!options?.ssr);
if (options.deno) {
await emitDenoOutput(rootDir, config, !!options.ssr);
}
}
Loading
Loading