aleph.js icon indicating copy to clipboard operation
aleph.js copied to clipboard

SWC Macro

Open shadowtime2000 opened this issue 4 years ago • 20 comments
trafficstars

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.

shadowtime2000 avatar Jan 03 '21 18:01 shadowtime2000

@ije Thoughts? @alfredosalzillo Are you still interested in creating such an env plugin?

shadowtime2000 avatar Jan 03 '21 19:01 shadowtime2000

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 avatar Jan 04 '21 03:01 ije

@ije Makes sense!

shadowtime2000 avatar Jan 04 '21 03:01 shadowtime2000

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

ije avatar Jan 04 '21 08:01 ije

with that, people can write their own macro that gives more power to define your code syntax.

ije avatar Jan 04 '21 08:01 ije

I agree. I prefer this solution too.

alfredosalzillo avatar Jan 04 '21 11:01 alfredosalzillo

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": [ ... ]
}

ije avatar Jan 04 '21 14:01 ije

I like the idea of an SWC macro, it could possibly then help us with #60.

shadowtime2000 avatar Jan 04 '21 16:01 shadowtime2000

@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.

shadowtime2000 avatar Jan 04 '21 16:01 shadowtime2000

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 avatar Jan 04 '21 17:01 ije

@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 avatar Jan 04 '21 18:01 shadowtime2000

@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.

ije avatar Jan 04 '21 19:01 ije

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.

shadowtime2000 avatar Jan 04 '21 19:01 shadowtime2000

@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 avatar Jan 04 '21 22:01 shadowtime2000

@shadowtime2000 you are right it's a bad idea to inject deno.env!

ije avatar Jan 05 '21 00:01 ije

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 avatar Jan 05 '21 00:01 ije

@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 avatar Jan 05 '21 01:01 shadowtime2000

@shadowtime2000 for sure

ije avatar Jan 05 '21 02:01 ije

We should probably allow returning an AST or something for more organized complex macros.

shadowtime2000 avatar Jan 15 '21 05:01 shadowtime2000

I think we should maybe instead just invoke a macro if macro data is present on the function.

shadowtime2000 avatar Jan 22 '21 06:01 shadowtime2000