Skip to content
This repository was archived by the owner on Jul 6, 2025. It is now read-only.

Commit ad689fe

Browse files
authored
Merge pull request #2 from alephjs/master
Refresh fork from alephjs/aleph.js
2 parents 12d136c + 011eb5e commit ad689fe

File tree

14 files changed

+92
-79
lines changed

14 files changed

+92
-79
lines changed

server/bundler.ts renamed to bundler/mod.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,16 @@ import * as path from 'https://deno.land/[email protected]/path/mod.ts'
33
import { ensureDir } from 'https://deno.land/[email protected]/fs/ensure_dir.ts'
44
import { parseExportNames, transform } from '../compiler/mod.ts'
55
import { trimModuleExt } from '../framework/core/module.ts'
6-
import { defaultReactVersion, defaultReactEsmShBuildVersion } from '../shared/constants.ts'
76
import { ensureTextFile, existsFileSync, lazyRemove } from '../shared/fs.ts'
87
import log from '../shared/log.ts'
98
import util from '../shared/util.ts'
109
import { VERSION } from '../version.ts'
11-
import type { Application, Module } from './app.ts'
10+
import type { Application, Module } from '../server/app.ts'
1211
import {
1312
clearCompilation,
1413
computeHash,
1514
getAlephPkgUri,
16-
isLoaderPlugin
17-
} from './helper.ts'
15+
} from '../server/helper.ts'
1816

1917
export const bundlerRuntimeCode = (`
2018
window.__ALEPH = {
@@ -211,7 +209,7 @@ export class Bundler {
211209
const bundleFilename = `polyfill.bundle.${hash.slice(0, 8)}.js`
212210
const bundleFile = path.join(this.#app.buildDir, bundleFilename)
213211
if (!existsFileSync(bundleFile)) {
214-
const rawPolyfillFile = `${alephPkgUri}/compiler/polyfills/${buildTarget}/mod.ts`
212+
const rawPolyfillFile = `${alephPkgUri}/bundler/polyfills/${buildTarget}/mod.ts`
215213
await this._bundle(rawPolyfillFile, bundleFile)
216214
}
217215
this.#bundledFiles.set('polyfill', bundleFilename)
File renamed without changes.

framework/react/anchor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ export default function Anchor(props: AnchorProps) {
121121
return
122122
}
123123
e.preventDefault()
124-
if (isCurrent) {
124+
if (!isCurrent) {
125125
redirect(href, replace)
126126
}
127127
}, [isCurrent, href, replace])

framework/react/hoc.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,19 @@ import { useDeno, useRouter } from './hooks.ts'
1313

1414
type ReactNode = ReactChild | ReactFragment | ReactPortal
1515

16+
// Any prop that has a default prop becomes optional, but its type is unchanged
17+
// Undeclared default props are augmented into the resulting allowable attributes
18+
// If declared props have indexed properties, ignore default props entirely as keyof gets widened
19+
// Wrap in an outer-level conditional type to allow distribution over props that are unions
20+
type Defaultize<P, D> = P extends any
21+
? string extends keyof P ? P :
22+
& Pick<P, Exclude<keyof P, keyof D>>
23+
& Partial<Pick<P, Extract<keyof P, keyof D>>>
24+
& Partial<Pick<D, Exclude<keyof D, keyof P>>>
25+
: never
26+
27+
type ReactManagedProps<C, P> = C extends { defaultProps: infer D } ? Defaultize<P, D> : P
28+
1629
/**
1730
* `withRouter` allows you to use `useRouter` hook with class component.
1831
*
@@ -66,12 +79,12 @@ export function withDeno<T>(callback: () => (T | Promise<T>), revalidate?: numbe
6679
* }
6780
* ```
6881
*
69-
* @param {Function} factory - load factory.
82+
* @param {Function} factory - dynamic loading factory.
7083
*/
7184
export function dynamic<T extends ComponentType<any>>(
7285
factory: () => Promise<{ default: T }>
73-
): ComponentType<ComponentPropsWithRef<T> & { fallback?: ReactNode }> {
74-
const DynamicComponent = ({ fallback, ...props }: ComponentPropsWithRef<T> & { fallback?: ReactNode }) => {
86+
): ComponentType<ReactManagedProps<T, ComponentPropsWithRef<T>> & { fallback?: ReactNode }> {
87+
const DynamicComponent = ({ fallback, ...props }: ReactManagedProps<T, ComponentPropsWithRef<T>> & { fallback?: ReactNode }) => {
7588
const [mod, setMod] = useState<{ default: T } | null>(null)
7689

7790
useEffect(() => {

framework/react/hooks.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export function useDeno<T = any>(callback: () => (T | Promise<T>), revalidate?:
4040
const dataUrl = 'pagedata://' + pathname
4141
const eventName = 'useDeno-' + dataUrl
4242
const key = dataUrl + '#' + id
43-
const expires = revalidate ? Date.now() + revalidate * 1000 : 0
43+
const expires = typeof revalidate === 'number' && !isNaN(revalidate) ? Date.now() + revalidate * 1000 : 0
4444
const renderingDataCache = global['rendering-' + dataUrl]
4545
if (renderingDataCache && key in renderingDataCache) {
4646
return renderingDataCache[key] // 2+ pass

import_map.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"imports": {
3-
"aleph/": "https://deno.land/x/[email protected].23/",
4-
"framework": "https://deno.land/x/[email protected].23/framework/core/mod.ts",
5-
"framework/react": "https://deno.land/x/[email protected].23/framework/react/mod.ts",
3+
"aleph/": "https://deno.land/x/[email protected].24/",
4+
"framework": "https://deno.land/x/[email protected].24/framework/core/mod.ts",
5+
"framework/react": "https://deno.land/x/[email protected].24/framework/react/mod.ts",
66
"react": "https://esm.sh/[email protected]",
77
"react-dom": "https://esm.sh/[email protected]"
88
}

server/app.ts

Lines changed: 23 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { bold, dim } from 'https://deno.land/[email protected]/fmt/colors.ts'
2-
import { walk } from 'https://deno.land/[email protected]/fs/walk.ts'
32
import { ensureDir } from 'https://deno.land/[email protected]/fs/ensure_dir.ts'
3+
import { walk } from 'https://deno.land/[email protected]/fs/walk.ts'
44
import { createHash } from 'https://deno.land/[email protected]/hash/mod.ts'
55
import {
66
basename,
@@ -9,7 +9,7 @@ import {
99
join,
1010
resolve
1111
} from 'https://deno.land/[email protected]/path/mod.ts'
12-
import { CSSProcessor } from '../compiler/css.ts'
12+
import { Bundler, bundlerRuntimeCode } from '../bundler/mod.ts'
1313
import {
1414
buildChecksum,
1515
ImportMap,
@@ -22,8 +22,7 @@ import { EventEmitter } from '../framework/core/events.ts'
2222
import { moduleExts, toPagePath, trimModuleExt } from '../framework/core/module.ts'
2323
import { RouteModule, Routing } from '../framework/core/routing.ts'
2424
import {
25-
defaultReactVersion,
26-
defaultReactEsmShBuildVersion,
25+
defaultReactEsmShBuildVersion, defaultReactVersion,
2726
minDenoVersion
2827
} from '../shared/constants.ts'
2928
import {
@@ -36,11 +35,11 @@ import util from '../shared/util.ts'
3635
import type {
3736
Config,
3837
RouterURL,
39-
ServerApplication,
38+
ServerApplication
4039
} from '../types.ts'
4140
import { VERSION } from '../version.ts'
42-
import { Bundler, bundlerRuntimeCode } from './bundler.ts'
43-
import { defaultConfig, loadConfig, loadImportMap, loadPostCSSConfig } from './config.ts'
41+
import { defaultConfig, loadConfig, loadImportMap } from './config.ts'
42+
import { CSSProcessor } from './css.ts'
4443
import {
4544
computeHash,
4645
formatBytesWithColor,
@@ -79,7 +78,6 @@ export class Application implements ServerApplication {
7978
readonly importMap: ImportMap
8079
readonly ready: Promise<void>
8180

82-
#dirs: Map<string, string> = new Map()
8381
#modules: Map<string, Module> = new Map()
8482
#pageRouting: Routing = new Routing({})
8583
#apiRouting: Routing = new Routing({})
@@ -109,20 +107,20 @@ export class Application implements ServerApplication {
109107
/** initiate application */
110108
private async init(reload: boolean) {
111109
let t = performance.now()
112-
const [config, importMap, postcssConfig] = await Promise.all([
110+
const [config, importMap,] = await Promise.all([
113111
loadConfig(this.workingDir),
114112
loadImportMap(this.workingDir),
115-
loadPostCSSConfig(this.workingDir),
116113
])
117114

118115
Object.assign(this.config, config)
119116
Object.assign(this.importMap, importMap)
120117
this.#pageRouting.config(this.config)
121-
this.#cssProcesser.config(!this.isDev, postcssConfig.plugins)
118+
this.#cssProcesser.config(!this.isDev, this.config.postcss.plugins)
122119

123120
// inject env variables
124121
Deno.env.set('ALEPH_VERSION', VERSION)
125-
Deno.env.set('BUILD_MODE', this.mode)
122+
Deno.env.set('ALEPH_BUILD_MODE', this.mode)
123+
Deno.env.set('ALEPH_FRAMEWORK', this.framework)
126124

127125
// inject browser navigator polyfill
128126
Object.assign((globalThis as any).navigator, {
@@ -149,7 +147,8 @@ export class Application implements ServerApplication {
149147
const buildManifestFile = join(this.buildDir, 'build.manifest.json')
150148
const configChecksum = computeHash(JSON.stringify({
151149
...this.sharedCompileOptions,
152-
plugins: this.config.plugins.filter(isLoaderPlugin).map(({ name }) => name)
150+
plugins: this.config.plugins.filter(isLoaderPlugin).map(({ name }) => name),
151+
postcssPlugins: this.config.postcss.plugins.map(p => p.toString())
153152
}, (key: string, value: any) => {
154153
if (key === 'inlineStylePreprocess') {
155154
return void 0
@@ -195,12 +194,12 @@ export class Application implements ServerApplication {
195194
}
196195

197196
// init framework
198-
const { init } = await import(`../framework/${this.config.framework}/init.ts`)
197+
const { init } = await import(`../framework/${this.framework}/init.ts`)
199198
await init(this)
200199

201200
// import framework renderer
202201
if (this.config.ssr) {
203-
const { jsFile } = await this.compile(`${alephPkgUri}/framework/${this.config.framework}/renderer.ts`)
202+
const { jsFile } = await this.compile(`${alephPkgUri}/framework/${this.framework}/renderer.ts`)
204203
const { render } = await import(`file://${jsFile}`)
205204
if (util.isFunction(render)) {
206205
this.#renderer.setFrameworkRenderer({ render })
@@ -210,7 +209,7 @@ export class Application implements ServerApplication {
210209
log.info('Compiling...')
211210

212211
// pre-compile framework modules
213-
await this.compile(`${alephPkgUri}/framework/${this.config.framework}/bootstrap.ts`)
212+
await this.compile(`${alephPkgUri}/framework/${this.framework}/bootstrap.ts`)
214213
if (this.isDev) {
215214
await this.compile(`${alephPkgUri}/framework/core/hmr.ts`)
216215
await this.compile(`${alephPkgUri}/framework/core/nomodule.ts`)
@@ -405,16 +404,20 @@ export class Application implements ServerApplication {
405404
return this.mode === 'development'
406405
}
407406

407+
get framework() {
408+
return this.config.framework
409+
}
410+
408411
get srcDir() {
409-
return this.getDir('src', () => join(this.workingDir, this.config.srcDir))
412+
return join(this.workingDir, this.config.srcDir)
410413
}
411414

412415
get outputDir() {
413-
return this.getDir('output', () => join(this.workingDir, this.config.outputDir))
416+
return join(this.workingDir, this.config.outputDir)
414417
}
415418

416419
get buildDir() {
417-
return this.getDir('build', () => join(this.workingDir, '.aleph', this.mode))
420+
return join(this.workingDir, '.aleph', this.mode)
418421
}
419422

420423
get loaders() {
@@ -757,16 +760,6 @@ export class Application implements ServerApplication {
757760
log.info(`Done in ${Math.round(performance.now() - start)}ms`)
758761
}
759762

760-
private getDir(name: string, init: () => string) {
761-
if (this.#dirs.has(name)) {
762-
return this.#dirs.get(name)!
763-
}
764-
765-
const dir = init()
766-
this.#dirs.set(name, dir)
767-
return dir
768-
}
769-
770763
private createRouteUpdate(url: string): [string, string, { isIndex?: boolean, useDeno?: boolean }] {
771764
const isBuiltinModule = moduleExts.some(ext => url.endsWith('.' + ext))
772765
let pagePath = isBuiltinModule ? toPagePath(url) : util.trimSuffix(url, '/pages')
@@ -1231,7 +1224,7 @@ export class Application implements ServerApplication {
12311224

12321225
// add framwork bootstrap module as shared entry
12331226
entryMods.set(
1234-
[`${getAlephPkgUri()}/framework/${this.config.framework}/bootstrap.ts`],
1227+
[`${getAlephPkgUri()}/framework/${this.framework}/bootstrap.ts`],
12351228
true
12361229
)
12371230

server/config.ts

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import { join } from 'https://deno.land/[email protected]/path/mod.ts'
2-
import type { PostCSSPlugin } from '../compiler/css.ts'
32
import type { ImportMap } from '../compiler/mod.ts'
43
import { defaultReactVersion } from '../shared/constants.ts'
54
import { existsFileSync, existsDirSync } from '../shared/fs.ts'
65
import log from '../shared/log.ts'
76
import util from '../shared/util.ts'
8-
import type { Config } from '../types.ts'
7+
import type { Config, PostCSSPlugin } from '../types.ts'
98
import { getAlephPkgUri, reLocaleID } from './helper.ts'
109

1110
export const defaultConfig: Readonly<Required<Config>> = {
@@ -19,6 +18,7 @@ export const defaultConfig: Readonly<Required<Config>> = {
1918
rewrites: {},
2019
ssr: {},
2120
plugins: [],
21+
postcss: { plugins: ['autoprefixer'] },
2222
headers: {},
2323
env: {},
2424
}
@@ -60,6 +60,7 @@ export async function loadConfig(workingDir: string): Promise<Config> {
6060
ssr,
6161
rewrites,
6262
plugins,
63+
postcss,
6364
headers,
6465
env,
6566
} = data
@@ -68,7 +69,10 @@ export async function loadConfig(workingDir: string): Promise<Config> {
6869
}
6970
if (util.isNEString(srcDir)) {
7071
config.srcDir = util.cleanPath(srcDir)
71-
} else if (existsDirSync(join(workingDir, 'src'))) {
72+
} else if (
73+
!existsDirSync(join(workingDir, 'pages')) &&
74+
existsDirSync(join(workingDir, 'src', 'pages'))
75+
) {
7276
config.srcDir = '/src'
7377
}
7478
if (util.isNEString(outputDir)) {
@@ -107,32 +111,16 @@ export async function loadConfig(workingDir: string): Promise<Config> {
107111
if (util.isNEArray(plugins)) {
108112
config.plugins = plugins
109113
}
114+
if (isPostcssConfig(postcss)) {
115+
config.postcss = postcss
116+
} else {
117+
config.postcss = await loadPostCSSConfig(workingDir)
118+
}
110119

111120
return config
112121
}
113122

114-
export async function loadPostCSSConfig(workingDir: string): Promise<{ plugins: PostCSSPlugin[] }> {
115-
for (const name of Array.from(['ts', 'js', 'json']).map(ext => `postcss.config.${ext}`)) {
116-
const p = join(workingDir, name)
117-
if (existsFileSync(p)) {
118-
let config: any = null
119-
if (name.endsWith('.json')) {
120-
config = JSON.parse(await Deno.readTextFile(p))
121-
} else {
122-
const mod = await import('file://' + p)
123-
config = mod.default
124-
if (util.isFunction(config)) {
125-
config = await config()
126-
}
127-
}
128-
if (isPostcssConfig(config)) {
129-
return config
130-
}
131-
}
132-
}
133123

134-
return { plugins: ['autoprefixer'] }
135-
}
136124

137125
/** load import maps from `import_map.json` */
138126
export async function loadImportMap(workingDir: string): Promise<ImportMap> {
@@ -169,6 +157,29 @@ export async function loadImportMap(workingDir: string): Promise<ImportMap> {
169157
return importMap
170158
}
171159

160+
async function loadPostCSSConfig(workingDir: string): Promise<{ plugins: PostCSSPlugin[] }> {
161+
for (const name of Array.from(['ts', 'js', 'json']).map(ext => `postcss.config.${ext}`)) {
162+
const p = join(workingDir, name)
163+
if (existsFileSync(p)) {
164+
let config: any = null
165+
if (name.endsWith('.json')) {
166+
config = JSON.parse(await Deno.readTextFile(p))
167+
} else {
168+
const mod = await import('file://' + p)
169+
config = mod.default
170+
if (util.isFunction(config)) {
171+
config = await config()
172+
}
173+
}
174+
if (isPostcssConfig(config)) {
175+
return config
176+
}
177+
}
178+
}
179+
180+
return { plugins: ['autoprefixer'] }
181+
}
182+
172183
function isFramework(v: any): v is 'react' {
173184
switch (v) {
174185
case 'react':

compiler/css.ts renamed to server/css.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
import { Plugin, PluginCreator } from 'https://esm.sh/[email protected]'
21
import util from '../shared/util.ts'
2+
import { PostCSSPlugin } from '../types.ts'
33

44
const postcssVersion = '8.2.8'
55
const productionOnlyPostcssPlugins = ['autoprefixer']
66

7-
export type PostCSSPlugin = string | [string, any] | Plugin | PluginCreator<any>
8-
97
export class CSSProcessor {
108
#isProd: boolean
119
#postcssPlugins: PostCSSPlugin[]
@@ -70,7 +68,7 @@ async function initCleanCSS() {
7068

7169
async function initPostCSS(plugins: PostCSSPlugin[]) {
7270
const { default: PostCSS } = await import(`https://esm.sh/postcss@${postcssVersion}`)
73-
const isDev = Deno.env.get('BUILD_MODE') === 'development'
71+
const isDev = Deno.env.get('ALEPH_BUILD_MODE') === 'development'
7472
return PostCSS(await Promise.all(plugins.filter(p => {
7573
if (isDev) {
7674
if (util.isNEString(p) && productionOnlyPostcssPlugins.includes(p)) {

0 commit comments

Comments
 (0)