aleph.js
aleph.js copied to clipboard
SWC Macro
A plugin to replace .env variables in a certain manner. Initially proposed in #77. Initial design used regex to replace anything surrounded by handlebars. I think we should use deno_swc which will allow us to instead replace Deno.env. anything. We could possibly look into requiring ALEPH_PUBLIC_ prefix to .env variables unless it is accessed inside a useDeno hook.
@ije Thoughts? @alfredosalzillo Are you still interested in creating such an env plugin?
maybe too much to import the deno_swc for the env plugin, 0.3 will include a new compiler using swc i can implement this function without plugin imported.
@ije Makes sense!
i perfer a new concept swc-marco can be a solution:
import env from 'https://deno.land/x/aleph/swc-macros/env.macro.ts'
const value = env('KEY')
it will be transpiled to below code:
const value = __ALEPH_ENV.get('KEY')
and the macro will export the deno.env as __ALEPH_ENV.
what do you think? @shadowtime2000 @alfredosalzillo
with that, people can write their own macro that gives more power to define your code syntax.
I agree. I prefer this solution too.
for example, we can transform graphql string to AST at build time with macro:
import gql from 'https://deno.land/x/aleph/macros/graphql.macro.ts'
const query = gql`
{
user(id: 123) {
firstName
lastName
}
}
`
output code:
const query = {
"kind": "Document",
"definitions": [ ... ]
}
I like the idea of an SWC macro, it could possibly then help us with #60.
@ije How exactly would this be written? Will we write it within the new compiler after it is merged or will we another repo for this project or something? I think SWC macros could be useful just all around in a ton of places.
it seems like:
// https://deno.land/x/aleph/swc-macros/env.macro.ts
export default function EnvMacro(key: string): string {
return ''
}
EnvMacro.macro = {
// inject code to `main.js` at ssr/ssg
inject(): string {
return `window.__ALEPH_ENV=${JSON.stringify(Deno.env)}`
},
// transform macro call expression
transform(arg0): string {
return `__ALEPH_ENV.get(${arg0})`
}
}
@ije Thx, but I was actually asking about how the compiler which expands the macros will be organized. I don't think we should have an inject method which injects that into the main file, I think it would be better if we just did something like this:
export default function EnvMacro(key: string): string {
return ''
}
EnvMacro.macro = {
transform(arg0): string {
return Deno.env.get(arg0);
}
}
@shadowtime2000 the transform should return a js code fragment that why i added the inject method(it's optional) to inject deno runtime variables. i will add the feature in the new compiler, no extra dependency needed.
Tbh, I feel like macros purely for a framework like this is a little overkill and we could look into creating a library for these macros that doesn't require Aleph to be used.
@ije I don't think it is a good idea to dump everything in Deno.env into a global namespace because there could be unused .env variables for stuff like API keys which could be used in the /api/ routes, which makes that a security concern. I think this should be good enough:
export default function EnvMacro(key: string): string {
return ''
}
EnvMacro.macro = {
transform(arg0): string {
return `"${Deno.env.get(arg0)}"`;
}
}
So env("foo") will be replaced with "bar".
@shadowtime2000 you are right it's a bad idea to inject deno.env!
i feel that the maco function is very easy to implement in the new compile with swc, if there is a statement like import macroFn from "./xxx.macro.ts", the macroFn will be treated as a macro. if we decide to implement it in a library then we need an ast compiler that is heavy.
@ije Good point, it would be easier to make it a library once there is a more standard form for ast modification and compilation and stuff.
@shadowtime2000 for sure
We should probably allow returning an AST or something for more organized complex macros.
I think we should maybe instead just invoke a macro if macro data is present on the function.