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

Commit 0647278

Browse files
committed
Merge branch 'rewrite-bundler' of https://github.com/alephjs/aleph.js into rewrite-bundler
2 parents 71f193b + 5d1502a commit 0647278

File tree

11 files changed

+260
-206
lines changed

11 files changed

+260
-206
lines changed

CONTRIBUTING.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ You will need [Deno](https://deno.land/) 1.7+.
2222

2323
```bash
2424
# set dev env
25-
echo 'ALEPH_DEV_PORT=2021' > .env.local
25+
echo 'ALEPH_DEV_PORT=2020' > .env.local
2626

2727
# ssr/development with HMR
2828
deno run -A --unstable cli.ts dev ./examples/hello-world -L debug
@@ -34,7 +34,7 @@ deno run -A --unstable cli.ts start ./examples/hello-world -L debug
3434
deno run -A --unstable cli.ts build ./examples/hello-world -L debug
3535

3636
# run all tests
37-
deno test -A --unstable --location=http://localhost
37+
deno test -A --unstable --location=https://deno.land/x/aleph
3838
```
3939

4040
## Project Structure

cli.ts

Lines changed: 40 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,15 @@ Options:
3333

3434
async function main() {
3535
const { _: args, ...options } = flags.parse(Deno.args)
36-
const hasCommand = args.length > 0 && args[0] in commands
37-
const command = (hasCommand ? String(args.shift()) : 'dev') as keyof typeof commands
3836

3937
// prints aleph.js version
40-
if (options.v && command != 'upgrade') {
38+
if (options.v) {
4139
console.log(`aleph.js v${VERSION}`)
4240
Deno.exit(0)
4341
}
4442

4543
// prints aleph.js and deno version
46-
if (options.version && command != 'upgrade') {
44+
if (options.version) {
4745
const { deno, v8, typescript } = Deno.version
4846
console.log([
4947
`aleph.js ${VERSION}`,
@@ -54,45 +52,48 @@ async function main() {
5452
Deno.exit(0)
5553
}
5654

57-
// prints help message
55+
// prints help message when the command not found
56+
if (!(args.length > 0 && args[0] in commands)) {
57+
console.log(helpMessage)
58+
Deno.exit(0)
59+
}
60+
61+
const command = String(args.shift()) as keyof typeof commands
62+
63+
// prints command help message
5864
if (options.h || options.help) {
59-
if (hasCommand) {
60-
import(`./cli/${command}.ts`).then(({ helpMessage }) => {
61-
console.log(commands[command] + '\n' + helpMessage)
62-
Deno.exit(0)
63-
})
64-
return
65-
} else {
65+
import(`./cli/${command}.ts`).then(({ helpMessage }) => {
66+
console.log(commands[command])
6667
console.log(helpMessage)
6768
Deno.exit(0)
68-
}
69+
})
70+
return
6971
}
7072

71-
// sets log level
72-
const l = options.L || options['log-level']
73-
if (util.isNEString(l)) {
74-
log.setLevel(l.toLowerCase() as LevelNames)
73+
// import command module
74+
const { default: cmd } = await import(`./cli/${command}.ts`)
75+
76+
// execute `init` command
77+
if (command === 'init') {
78+
await cmd(args[0])
79+
return
7580
}
7681

77-
if (!hasCommand && !args[0]) {
78-
const walkOptions = { includeDirs: false, exts: ['.js', '.jsx', '.mjs', '.ts', '.tsx'], skip: [/\.d\.ts$/i], dep: 1 }
79-
const pagesDir = path.join(path.resolve('.'), 'pages')
80-
let hasIndexPage = false
81-
if (existsDirSync(pagesDir)) {
82-
for await (const { path: p } of walk(pagesDir, walkOptions)) {
83-
if (path.basename(p).split('.')[0] === 'index') {
84-
hasIndexPage = true
85-
}
86-
}
87-
}
88-
if (!hasIndexPage) {
89-
console.log(helpMessage)
90-
Deno.exit(0)
91-
}
82+
// execute `upgrade` command
83+
if (command === 'upgrade') {
84+
await cmd(options.v || options.version || args[0] || 'latest')
85+
return
86+
}
87+
88+
// check working Dir
89+
const workingDir = path.resolve(String(args[0] || '.'))
90+
if (!existsDirSync(workingDir)) {
91+
log.fatal('No such directory:', workingDir)
9292
}
93+
Deno.chdir(workingDir)
9394

9495
// load .env
95-
for await (const { path: p, } of walk(Deno.cwd(), { match: [/(^|\/|\\)\.env(\.|$)/i], maxDepth: 1 })) {
96+
for await (const { path: p, } of walk(workingDir, { match: [/(^|\/|\\)\.env(\.|$)/i], maxDepth: 1 })) {
9697
const text = await Deno.readTextFile(p)
9798
text.split('\n').forEach(line => {
9899
let [key, value] = util.splitBy(line, '=')
@@ -110,23 +111,13 @@ async function main() {
110111
localProxy(parseInt(v))
111112
}
112113

113-
const { default: cmd } = await import(`./cli/${command}.ts`)
114-
switch (command) {
115-
case 'init':
116-
await cmd(args[0])
117-
break
118-
case 'upgrade':
119-
await cmd(options.v || options.version || args[0] || 'latest')
120-
break
121-
default:
122-
const workingDir = path.resolve(String(args[0] || '.'))
123-
if (!existsDirSync(workingDir)) {
124-
log.fatal('No such directory:', workingDir)
125-
}
126-
Deno.chdir(workingDir)
127-
await cmd(workingDir, options)
128-
break
114+
// sets log level
115+
const l = options.L || options['log-level']
116+
if (util.isNEString(l)) {
117+
log.setLevel(l.toLowerCase() as LevelNames)
129118
}
119+
120+
await cmd(workingDir, options)
130121
}
131122

132123
if (import.meta.main) {

cli/upgrade.ts

Lines changed: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
1-
import { colors } from '../deps.ts'
2-
import { VERSION } from '../version.ts'
1+
import { colors, path } from '../deps.ts'
2+
import { existsFileSync } from '../shared/fs.ts'
3+
4+
const versionMetaUrl = 'https://cdn.deno.land/aleph/meta/versions.json'
35

46
export const helpMessage = `
57
Usage:
68
aleph upgrade
79
810
Options:
9-
-v, --version <version> The upgrading version
11+
--version <version> The version to upgrade to
1012
-h, --help Prints help message
1113
`
1214

13-
export default async function (version: string) {
15+
export default async function (version = 'latest') {
1416
console.log('Looking up latest version...')
15-
const metaUrl = 'https://cdn.deno.land/aleph/meta/versions.json'
16-
const { latest, versions } = await (await fetch(metaUrl)).json()
17+
const { latest, versions } = await (await fetch(versionMetaUrl)).json()
1718
if (version === 'latest') {
1819
version = latest
1920
} else if (!versions.includes(version)) {
@@ -23,17 +24,31 @@ export default async function (version: string) {
2324
Deno.exit(1)
2425
}
2526
}
26-
if (version === 'v' + VERSION) {
27-
console.log('Already up-to-date!')
28-
Deno.exit(0)
29-
}
27+
28+
const denoExecPath = Deno.execPath()
29+
const cmdExists = existsFileSync(path.join(path.dirname(denoExecPath), 'aleph'))
3030
const p = Deno.run({
31-
cmd: [Deno.execPath(), 'install', '-A', '-f', '--location', 'http://localhost', '-n', 'aleph', `https://deno.land/x/aleph@${version}/cli.ts`],
31+
cmd: [
32+
denoExecPath,
33+
'install',
34+
'-A',
35+
'-f',
36+
'--unstable',
37+
'-n', 'aleph',
38+
'--location', 'https://deno.land/x/aleph',
39+
`https://deno.land/x/aleph@${version}/cli.ts`
40+
],
3241
stdout: 'null',
33-
stderr: 'piped'
42+
stderr: 'inherit'
3443
})
35-
Deno.stderr.write(await p.stderrOutput())
36-
console.log(`Aleph.js is up to ${version}!`)
37-
p.close()
38-
Deno.exit(0)
44+
const status = await p.status()
45+
if (status.success) {
46+
if (cmdExists) {
47+
console.log(`Aleph.js is up to ${version}!`)
48+
} else {
49+
console.log('Aleph.js was installed successfully!')
50+
console.log(`Run 'aleph --help' to get started`)
51+
}
52+
}
53+
Deno.exit(status.code)
3954
}

compiler/mod.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ export type TransformOptions = {
4343
export type TransformResult = {
4444
code: string
4545
deps: DependencyDescriptor[]
46+
bundleStarExports?: string[]
4647
map?: string
4748
}
4849

@@ -120,7 +121,7 @@ export async function transform(url: string, code: string, options: TransformOpt
120121
}
121122

122123
const { loaders, ...transformOptions } = options
123-
let { code: jsContent, inlineStyles, deps, map } = transformSync(url, code, transformOptions)
124+
let { code: jsContent, deps, map, inlineStyles, bundleStarExports } = transformSync(url, code, transformOptions)
124125

125126
// resolve inline-style
126127
await Promise.all(Object.entries(inlineStyles as InlineStyles).map(async ([key, style]) => {
@@ -165,7 +166,7 @@ export async function transform(url: string, code: string, options: TransformOpt
165166
jsContent = jsContent.replace(`"%%${key}-placeholder%%"`, '`' + tpl + '`')
166167
}))
167168

168-
return { code: jsContent, deps, map }
169+
return { code: jsContent, deps, map, bundleStarExports }
169170
}
170171

171172
/* parse export names of the module */

compiler/src/lib.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ pub struct TransformOutput {
9999
pub map: Option<String>,
100100
pub deps: Vec<DependencyDescriptor>,
101101
pub inline_styles: HashMap<String, InlineStyle>,
102-
pub star_exports: Vec<String>,
102+
pub bundle_star_exports: Option<Vec<String>>,
103103
}
104104

105105
#[wasm_bindgen(js_name = "parseExportNamesSync")]
@@ -163,7 +163,11 @@ pub fn transform_sync(url: &str, code: &str, options: JsValue) -> Result<JsValue
163163
map,
164164
deps: r.dep_graph.clone(),
165165
inline_styles: r.inline_styles.clone(),
166-
star_exports: r.star_exports.clone(),
166+
bundle_star_exports: if r.bundle_star_exports.len() > 0 {
167+
Some(r.bundle_star_exports.clone())
168+
} else {
169+
None
170+
},
167171
})
168172
.unwrap(),
169173
)

compiler/src/resolve.rs

Lines changed: 15 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ lazy_static! {
1919
)
2020
.unwrap();
2121
pub static ref RE_REACT_URL: Regex = Regex::new(
22-
r"^https?://(esm.sh/|cdn.esm.sh/v\d+/|esm.x-static.io/v\d+/|jspm.dev/|cdn.skypack.dev/|jspm.dev/npm:|esm.run/)react(\-dom)?(@[\^|~]{0,1}[0-9a-z\.\-]+)?([/|\?].*)?$"
22+
r"^https?://(esm.sh/|cdn.esm.sh/v\d+/|cdn.esm.sh.cn/v\d+/|esm.x-static.io/v\d+/)react(\-dom)?(@[\^|~]{0,1}[0-9a-z\.\-]+)?([/|\?].*)?$"
2323
)
2424
.unwrap();
2525
}
@@ -45,20 +45,20 @@ pub struct Resolver {
4545
pub specifier: String,
4646
/// a flag indicating if the specifier is remote url or not.
4747
pub specifier_is_remote: bool,
48-
/// builtin jsx tags like `a`, `link`, `head`, etc
49-
pub used_builtin_jsx_tags: IndexSet<String>,
5048
/// dependency graph
5149
pub dep_graph: Vec<DependencyDescriptor>,
52-
/// star exports
53-
pub star_exports: Vec<String>,
5450
/// inline styles
5551
pub inline_styles: HashMap<String, InlineStyle>,
5652
/// bundle mode
5753
pub bundle_mode: bool,
5854
/// bundled modules
5955
pub bundle_external: IndexSet<String>,
56+
/// bundle star exports
57+
pub bundle_star_exports: Vec<String>,
6058
/// extra imports
6159
pub extra_imports: IndexSet<String>,
60+
/// builtin jsx tags like `a`, `link`, `head`, etc
61+
pub used_builtin_jsx_tags: IndexSet<String>,
6262

6363
// private
6464
import_map: ImportMap,
@@ -84,7 +84,7 @@ impl Resolver {
8484
specifier_is_remote: is_remote_url(specifier),
8585
used_builtin_jsx_tags: IndexSet::new(),
8686
dep_graph: Vec::new(),
87-
star_exports: Vec::new(),
87+
bundle_star_exports: Vec::new(),
8888
inline_styles: HashMap::new(),
8989
import_map: ImportMap::from_hashmap(import_map),
9090
aleph_pkg_uri,
@@ -108,13 +108,10 @@ impl Resolver {
108108

109109
/// fix import/export url.
110110
// - `https://esm.sh/react` -> `/-/esm.sh/react.js`
111-
// - `https://esm.sh/[email protected]?target=es2015&dev` -> `/-/esm.sh/[email protected].1_target=es2015&dev.js`
111+
// - `https://esm.sh/[email protected]?target=es2015&dev` -> `/-/esm.sh/[base64('target=es2015&dev')][email protected].1.js`
112112
// - `http://localhost:8080/mod` -> `/-/http_localhost_8080/mod.js`
113-
// - `/components/logo.tsx` -> `/components/logo.tsx`
114-
// - `../components/logo.tsx` -> `../components/logo.tsx`
115-
// - `./button.tsx` -> `./button.tsx`
116-
// - `/components/foo/./logo.tsx` -> `/components/foo/logo.tsx`
117-
// - `/components/foo/../logo.tsx` -> `/components/logo.tsx`
113+
// - `/components/x/./logo.tsx` -> `/components/x/logo.tsx`
114+
// - `/components/x/../logo.tsx` -> `/components/logo.tsx`
118115
pub fn fix_import_url(&self, url: &str) -> String {
119116
let is_remote = is_remote_url(url);
120117
if !is_remote {
@@ -194,8 +191,8 @@ impl Resolver {
194191
// [/pages/index.tsx]
195192
// - `https://esm.sh/swr` -> `../-/esm.sh/swr.js`
196193
// - `https://esm.sh/react` -> `../-/esm.sh/react@${REACT_VERSION}.js`
197-
// - `https://deno.land/x/aleph/mod.ts` -> `../-/deno.land/x/aleph@v${CURRENT_ALEPH_VERSION}/mod.ts`
198-
// - `../components/logo.tsx` -> `../components/logo.js#/styles/app.css@000000`
194+
// - `https://deno.land/x/aleph/mod.ts` -> `../-/deno.land/x/aleph@v${ALEPH_VERSION}/mod.ts`
195+
// - `../components/logo.tsx` -> `../components/logo.js#/components/logo.tsx@000000`
199196
// - `../styles/app.css` -> `../styles/app.css.js#/styles/app.css@000000`
200197
pub fn resolve(&mut self, url: &str, is_dynamic: bool) -> (String, String) {
201198
// apply import map
@@ -328,12 +325,8 @@ impl Resolver {
328325
.unwrap()
329326
.trim_end_matches(s)
330327
.to_owned();
331-
if self.bundle_mode {
332-
if is_dynamic {
333-
filename.push_str("bundle.");
334-
} else {
335-
filename.push_str("bundling.");
336-
}
328+
if self.bundle_mode && !is_dynamic {
329+
filename.push_str("bundling.");
337330
}
338331
filename.push_str("js");
339332
if !is_remote && !self.specifier_is_remote {
@@ -351,12 +344,8 @@ impl Resolver {
351344
.to_str()
352345
.unwrap()
353346
.to_owned();
354-
if self.bundle_mode {
355-
if is_dynamic {
356-
filename.push_str(".bundle");
357-
} else {
358-
filename.push_str(".bundling");
359-
}
347+
if self.bundle_mode && !is_dynamic {
348+
filename.push_str(".bundling");
360349
}
361350
filename.push_str(".js#");
362351
filename.push_str(fixed_url.as_str());

0 commit comments

Comments
 (0)