jiek 2.2.0 → 2.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin-helper.cjs +11 -4
- package/dist/cli-only-build.cjs +239 -127
- package/dist/cli-only-build.js +249 -137
- package/dist/rollup/index.cjs +22 -5
- package/dist/rollup/index.js +22 -5
- package/package.json +7 -3
- package/src/commands/build/analyzer.ts +122 -0
- package/src/commands/build/client/analyzer.tsx +121 -0
- package/src/commands/build/client/index.ts +28 -0
- package/src/commands/build.ts +25 -153
- package/src/commands/utils/optionParser.ts +4 -0
- package/src/rollup/index.ts +23 -4
- package/src/server.ts +9 -1
- package/src/utils/checkDependency.ts +22 -0
- package/src/utils/ts.ts +3 -3
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "jiek",
|
3
3
|
"type": "module",
|
4
|
-
"version": "2.2.
|
4
|
+
"version": "2.2.2",
|
5
5
|
"description": "A lightweight toolkit for compiling and managing libraries based on `package.json` metadata and suitable for `Monorepo`.",
|
6
6
|
"author": "YiJie <yijie4188@gmail.com>",
|
7
7
|
"homepage": "https://github.com/NWYLZW/jiek/tree/master/packages/jiek#readme",
|
@@ -48,7 +48,11 @@
|
|
48
48
|
}
|
49
49
|
},
|
50
50
|
"imports": {
|
51
|
-
"#~/*":
|
51
|
+
"#~/*": [
|
52
|
+
"./src/*",
|
53
|
+
"./src/*/index.ts",
|
54
|
+
"./src/*/index.tsx"
|
55
|
+
]
|
52
56
|
},
|
53
57
|
"bin": {
|
54
58
|
"jiek": "bin/jiek.js",
|
@@ -65,7 +69,7 @@
|
|
65
69
|
"rollup-plugin-postcss": "^4.0.2",
|
66
70
|
"rollup-plugin-swc3": "^0.12.1",
|
67
71
|
"typescript": "^4.0.0||^5.0.0",
|
68
|
-
"vite-bundle-analyzer": "
|
72
|
+
"vite-bundle-analyzer": "0.16.0-beta.1"
|
69
73
|
},
|
70
74
|
"dependencies": {
|
71
75
|
"@inquirer/prompts": "^7.1.0",
|
@@ -0,0 +1,122 @@
|
|
1
|
+
import type { Command } from 'commander'
|
2
|
+
|
3
|
+
import { CLIENT_CUSTOM_RENDER_SCRIPT } from '#~/commands/build/client/index.ts'
|
4
|
+
import { parseBoolean } from '#~/commands/utils/optionParser.ts'
|
5
|
+
import type { Module } from '#~/rollup/bundle-analyzer.ts'
|
6
|
+
import type { createServer } from '#~/server.ts'
|
7
|
+
import { checkDependency } from '#~/utils/checkDependency.ts'
|
8
|
+
import { existsSync, mkdirSync, statSync, writeFileSync } from 'node:fs'
|
9
|
+
import path from 'node:path'
|
10
|
+
|
11
|
+
export interface AnalyzerBuildOptions {
|
12
|
+
ana?: boolean
|
13
|
+
/**
|
14
|
+
* @default '.jk-analyses'
|
15
|
+
*/
|
16
|
+
'ana.dir': string
|
17
|
+
/**
|
18
|
+
* @default 'server'
|
19
|
+
*/
|
20
|
+
'ana.mode': string
|
21
|
+
'ana.open'?: boolean
|
22
|
+
/**
|
23
|
+
* @default 'parsed'
|
24
|
+
*/
|
25
|
+
'ana.size': string
|
26
|
+
}
|
27
|
+
|
28
|
+
export const registerAnalyzerCommandOptions = (command: Command) =>
|
29
|
+
command
|
30
|
+
.option('--ana', 'Enable the bundle analyzer.', parseBoolean)
|
31
|
+
.option('--ana.dir <DIR>', 'The directory of the bundle analyzer.', '.jk-analyses')
|
32
|
+
.option(
|
33
|
+
'--ana.mode <MODE>',
|
34
|
+
'The mode of the bundle analyzer, support "static", "json" and "server".',
|
35
|
+
'server'
|
36
|
+
)
|
37
|
+
.option('--ana.open', 'Open the bundle analyzer in the browser.', parseBoolean)
|
38
|
+
.option(
|
39
|
+
'--ana.size <SIZE>',
|
40
|
+
'The default size of the bundle analyzer, support "stat", "parsed" and "gzip".',
|
41
|
+
'parsed'
|
42
|
+
)
|
43
|
+
|
44
|
+
export const useAnalyzer = async (options: AnalyzerBuildOptions, server?: ReturnType<typeof createServer>) => {
|
45
|
+
const modules: Module[] = []
|
46
|
+
let bundleAnalyzerModule: typeof import('vite-bundle-analyzer') | undefined
|
47
|
+
const analyzer = options.ana
|
48
|
+
? {
|
49
|
+
dir: options['ana.dir'],
|
50
|
+
mode: options['ana.mode'],
|
51
|
+
open: options['ana.open'],
|
52
|
+
size: options['ana.size']
|
53
|
+
}
|
54
|
+
: undefined
|
55
|
+
if (
|
56
|
+
options.ana
|
57
|
+
&& ![
|
58
|
+
'stat',
|
59
|
+
'parsed',
|
60
|
+
'gzip'
|
61
|
+
].includes(analyzer?.size ?? '')
|
62
|
+
) {
|
63
|
+
throw new Error('The value of `ana.size` must be "stat", "parsed" or "gzip"')
|
64
|
+
}
|
65
|
+
|
66
|
+
if (analyzer) {
|
67
|
+
await checkDependency('vite-bundle-analyzer')
|
68
|
+
bundleAnalyzerModule = await import('vite-bundle-analyzer')
|
69
|
+
}
|
70
|
+
|
71
|
+
const refreshAnalyzer = async (cwd: string, applyModules: typeof modules) => {
|
72
|
+
if (!(analyzer && server && bundleAnalyzerModule)) return
|
73
|
+
|
74
|
+
if (analyzer.mode === 'json') {
|
75
|
+
const anaDir = path.resolve(cwd, analyzer.dir)
|
76
|
+
if (!existsSync(anaDir)) {
|
77
|
+
mkdirSync(anaDir, { recursive: true })
|
78
|
+
}
|
79
|
+
const gitIgnorePath = path.resolve(anaDir, '.gitignore')
|
80
|
+
if (!existsSync(gitIgnorePath)) {
|
81
|
+
writeFileSync(gitIgnorePath, '*\n!.gitignore\n')
|
82
|
+
}
|
83
|
+
const npmIgnorePath = path.resolve(anaDir, '.npmignore')
|
84
|
+
if (!existsSync(npmIgnorePath)) {
|
85
|
+
writeFileSync(npmIgnorePath, '*\n')
|
86
|
+
}
|
87
|
+
if (!statSync(anaDir).isDirectory()) {
|
88
|
+
throw new Error(`The directory '${anaDir}' is not a directory.`)
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
const { renderView, injectHTMLTag } = bundleAnalyzerModule
|
93
|
+
applyModules.forEach(m => {
|
94
|
+
const index = modules.findIndex(({ filename }) => filename === m.filename)
|
95
|
+
if (index === -1) {
|
96
|
+
modules.push(m)
|
97
|
+
} else {
|
98
|
+
modules[index] = m
|
99
|
+
}
|
100
|
+
})
|
101
|
+
let html = await renderView(modules, {
|
102
|
+
title: `Jiek Analyzer`,
|
103
|
+
mode: analyzer.size as 'stat' | 'parsed' | 'gzip'
|
104
|
+
})
|
105
|
+
html = injectHTMLTag({
|
106
|
+
html,
|
107
|
+
injectTo: 'body',
|
108
|
+
descriptors: [
|
109
|
+
{ kind: 'script', text: CLIENT_CUSTOM_RENDER_SCRIPT }
|
110
|
+
]
|
111
|
+
})
|
112
|
+
void server.renderTo('/ana', html)
|
113
|
+
}
|
114
|
+
|
115
|
+
return {
|
116
|
+
modules,
|
117
|
+
refreshAnalyzer,
|
118
|
+
ANALYZER_ENV: {
|
119
|
+
JIEK_ANALYZER: analyzer ? JSON.stringify(analyzer) : undefined
|
120
|
+
}
|
121
|
+
}
|
122
|
+
}
|
@@ -0,0 +1,121 @@
|
|
1
|
+
import type { Module } from '#~/rollup/bundle-analyzer.ts'
|
2
|
+
|
3
|
+
interface Node {
|
4
|
+
id: string
|
5
|
+
filename: string
|
6
|
+
parent?: Node
|
7
|
+
}
|
8
|
+
|
9
|
+
declare global {
|
10
|
+
// @ts-ignore
|
11
|
+
// eslint-disable-next-line no-var,vars-on-top
|
12
|
+
var React: typeof import('react')
|
13
|
+
// eslint-disable-next-line no-var,vars-on-top
|
14
|
+
var analyzeModule: Module[]
|
15
|
+
interface WindowEventMap {
|
16
|
+
'graph:click': CustomEvent<
|
17
|
+
| undefined
|
18
|
+
| { node: Node }
|
19
|
+
>
|
20
|
+
'send:filter': CustomEvent<{
|
21
|
+
analyzeModule: Module[]
|
22
|
+
}>
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
export function Main() {
|
27
|
+
const { useState, useMemo, useEffect, useCallback } = React
|
28
|
+
const [path, setPath] = useState(() => location.pathname.replace(/^\/ana\/?/, ''))
|
29
|
+
const [pkgName, entry] = useMemo(() => {
|
30
|
+
const pkgName = /^(@[^/]+\/[^/]+|[^/]+)\/?/.exec(path)?.[1]
|
31
|
+
return [
|
32
|
+
pkgName,
|
33
|
+
(pkgName != null) ? path.replace(`${pkgName}/`, '') : undefined
|
34
|
+
]
|
35
|
+
}, [path])
|
36
|
+
const push = useCallback((newPath: string) => {
|
37
|
+
setPath(newPath)
|
38
|
+
document.title = `${document.title.replace(/ - \/.*/, '')} - \/${newPath}`
|
39
|
+
history.pushState(null, '', `/ana/${newPath}`)
|
40
|
+
}, [])
|
41
|
+
const filterModules = useCallback((startWith: string) => {
|
42
|
+
const modules = analyzeModule.filter(m => m.filename.startsWith(startWith))
|
43
|
+
dispatchEvent(new CustomEvent('send:filter', { detail: { analyzeModule: modules } }))
|
44
|
+
}, [])
|
45
|
+
useEffect(() => {
|
46
|
+
if (path !== '') {
|
47
|
+
document.title = `${document.title.replace(/ - \/.*/, '')} - \/${path}`
|
48
|
+
} else {
|
49
|
+
document.title = document.title.replace(/ - \/.*/, '')
|
50
|
+
}
|
51
|
+
filterModules(path)
|
52
|
+
}, [path, filterModules])
|
53
|
+
useEffect(() => {
|
54
|
+
const offGraphClick = listen('graph:click', ({ detail }) => {
|
55
|
+
if (!detail) return
|
56
|
+
|
57
|
+
let root = detail.node
|
58
|
+
while (root.parent) {
|
59
|
+
root = root.parent
|
60
|
+
}
|
61
|
+
if (root.filename === path) return
|
62
|
+
push(root.filename)
|
63
|
+
})
|
64
|
+
return () => {
|
65
|
+
offGraphClick()
|
66
|
+
}
|
67
|
+
}, [push])
|
68
|
+
function listen<T extends keyof WindowEventMap>(type: T, listener: (this: Window, ev: WindowEventMap[T]) => any) {
|
69
|
+
window.addEventListener(type, listener)
|
70
|
+
return () => {
|
71
|
+
window.removeEventListener(type, listener)
|
72
|
+
}
|
73
|
+
}
|
74
|
+
return (
|
75
|
+
<div
|
76
|
+
style={{
|
77
|
+
padding: '12px 55px'
|
78
|
+
}}
|
79
|
+
>
|
80
|
+
/
|
81
|
+
<select
|
82
|
+
style={{
|
83
|
+
appearance: 'none',
|
84
|
+
border: 'none',
|
85
|
+
background: 'none'
|
86
|
+
}}
|
87
|
+
value={pkgName}
|
88
|
+
onChange={e => push(e.target.value)}
|
89
|
+
>
|
90
|
+
<option value=''>All</option>
|
91
|
+
{analyzeModule
|
92
|
+
.map(m => /^(@[^/]+\/[^/]+|[^/]+)\/?/.exec(m.filename)?.[1])
|
93
|
+
.filter((v, i, a) => a.indexOf(v) === i)
|
94
|
+
.map(v => (
|
95
|
+
<option key={v} value={v}>{v}</option>
|
96
|
+
))}
|
97
|
+
</select>
|
98
|
+
{pkgName != null && <>
|
99
|
+
/
|
100
|
+
<select
|
101
|
+
style={{
|
102
|
+
appearance: 'none',
|
103
|
+
border: 'none',
|
104
|
+
background: 'none'
|
105
|
+
}}
|
106
|
+
value={entry}
|
107
|
+
onChange={e => push(`${pkgName}/${e.target.value}`)}
|
108
|
+
>
|
109
|
+
<option value=''>All</option>
|
110
|
+
{analyzeModule
|
111
|
+
.filter(m => m.filename.startsWith(`${pkgName}/`))
|
112
|
+
.map(m => m.filename.replace(`${pkgName}/`, ''))
|
113
|
+
.filter((v, i, a) => a.indexOf(v) === i)
|
114
|
+
.map(v => (
|
115
|
+
<option key={v} value={v}>{v}</option>
|
116
|
+
))}
|
117
|
+
</select>
|
118
|
+
</>}
|
119
|
+
</div>
|
120
|
+
)
|
121
|
+
}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
import { Main } from './analyzer'
|
2
|
+
|
3
|
+
declare global {
|
4
|
+
// eslint-disable-next-line no-var,vars-on-top
|
5
|
+
var CUSTOM_SIDE_BAR: boolean
|
6
|
+
// eslint-disable-next-line no-var,vars-on-top
|
7
|
+
var __REPLACE_INJECT__: string
|
8
|
+
}
|
9
|
+
|
10
|
+
function render() {
|
11
|
+
CUSTOM_SIDE_BAR = true
|
12
|
+
window.addEventListener('client:ready', () =>
|
13
|
+
setTimeout(() => {
|
14
|
+
window.dispatchEvent(
|
15
|
+
new CustomEvent('send:ui', {
|
16
|
+
detail: { type: 'Main', Component: __REPLACE_INJECT__ }
|
17
|
+
})
|
18
|
+
)
|
19
|
+
}, 0))
|
20
|
+
}
|
21
|
+
|
22
|
+
export const CLIENT_CUSTOM_RENDER_SCRIPT = [
|
23
|
+
Main.toString(),
|
24
|
+
render
|
25
|
+
.toString()
|
26
|
+
.replace('__REPLACE_INJECT__', Main.name),
|
27
|
+
`(${render.name})()`
|
28
|
+
].join('\n')
|
package/src/commands/build.ts
CHANGED
@@ -1,24 +1,24 @@
|
|
1
|
-
import { existsSync, mkdirSync,
|
1
|
+
import { existsSync, mkdirSync, writeFileSync } from 'node:fs'
|
2
2
|
import { createRequire } from 'node:module'
|
3
3
|
import path from 'node:path'
|
4
4
|
import process from 'node:process'
|
5
5
|
|
6
|
-
import { confirm } from '@inquirer/prompts'
|
7
6
|
import { MultiBar, Presets } from 'cli-progress'
|
8
7
|
import { program } from 'commander'
|
9
8
|
import { execaCommand } from 'execa'
|
10
|
-
import type { renderView } from 'vite-bundle-analyzer'
|
11
9
|
|
12
10
|
import type { RollupBuildEvent } from '#~/bridge.ts'
|
11
|
+
import type { AnalyzerBuildOptions } from '#~/commands/build/analyzer.ts'
|
12
|
+
import { registerAnalyzerCommandOptions, useAnalyzer } from '#~/commands/build/analyzer.ts'
|
13
13
|
import { entriesDescription, filterDescription, outdirDescription } from '#~/commands/descriptions.ts'
|
14
14
|
import { IS_WORKSPACE } from '#~/commands/meta.ts'
|
15
|
+
import { parseBoolean } from '#~/commands/utils/optionParser.ts'
|
15
16
|
import type { TemplateOptions } from '#~/rollup/base.ts'
|
16
17
|
import { BUILDER_TYPES, BUILDER_TYPE_PACKAGE_NAME_MAP } from '#~/rollup/base.ts'
|
17
|
-
import type { Module } from '#~/rollup/bundle-analyzer.ts'
|
18
18
|
import { createServer } from '#~/server.ts'
|
19
|
+
import { checkDependency } from '#~/utils/checkDependency.ts'
|
19
20
|
import type { ProjectsGraph } from '#~/utils/filterSupport.ts'
|
20
21
|
import { filterPackagesGraph, getSelectedProjectsGraph } from '#~/utils/filterSupport.ts'
|
21
|
-
import { getWD } from '#~/utils/getWD.ts'
|
22
22
|
import { loadConfig } from '#~/utils/loadConfig.ts'
|
23
23
|
import { tsRegisterName } from '#~/utils/tsRegister.ts'
|
24
24
|
|
@@ -49,21 +49,7 @@ If you want to through the options to the \`rollup\` command, you can pass the o
|
|
49
49
|
${isDefault ? 'This command is the default command.' : ''}
|
50
50
|
`.trim()
|
51
51
|
|
52
|
-
interface BuildOptions {
|
53
|
-
ana?: boolean
|
54
|
-
/**
|
55
|
-
* @default '.jk-analyses'
|
56
|
-
*/
|
57
|
-
'ana.dir': string
|
58
|
-
/**
|
59
|
-
* @default 'server'
|
60
|
-
*/
|
61
|
-
'ana.mode': string
|
62
|
-
'ana.open'?: boolean
|
63
|
-
/**
|
64
|
-
* @default 'parsed'
|
65
|
-
*/
|
66
|
-
'ana.size': string
|
52
|
+
interface BuildOptions extends AnalyzerBuildOptions {
|
67
53
|
/**
|
68
54
|
* Auto-detect the builder from the installed dependencies.
|
69
55
|
* If the builder is not installed, it will prompt the user to install it.
|
@@ -120,22 +106,6 @@ interface BuildOptions {
|
|
120
106
|
dtsconfig?: string
|
121
107
|
}
|
122
108
|
|
123
|
-
async function checkDependency(dependency: string) {
|
124
|
-
try {
|
125
|
-
require.resolve(dependency)
|
126
|
-
} catch {
|
127
|
-
console.error(`The package '${dependency}' is not installed, please install it first.`)
|
128
|
-
const { notWorkspace } = getWD()
|
129
|
-
const command = `pnpm install -${notWorkspace ? '' : 'w'}D ${dependency}`
|
130
|
-
if (await confirm({ message: 'Do you want to install it now?' })) {
|
131
|
-
await execaCommand(command)
|
132
|
-
} else {
|
133
|
-
console.warn(`You can run the command '${command}' to install it manually.`)
|
134
|
-
process.exit(1)
|
135
|
-
}
|
136
|
-
}
|
137
|
-
}
|
138
|
-
|
139
109
|
let DEFAULT_BUILDER_TYPE: typeof BUILDER_TYPES[number]
|
140
110
|
Object.entries(BUILDER_TYPE_PACKAGE_NAME_MAP).forEach(([type, packageName]) => {
|
141
111
|
try {
|
@@ -147,11 +117,6 @@ if (!DEFAULT_BUILDER_TYPE!) {
|
|
147
117
|
DEFAULT_BUILDER_TYPE = 'esbuild'
|
148
118
|
}
|
149
119
|
|
150
|
-
function parseBoolean(v?: unknown) {
|
151
|
-
if (v === undefined) return true
|
152
|
-
return Boolean(v)
|
153
|
-
}
|
154
|
-
|
155
120
|
const buildFilterDescription = `
|
156
121
|
${filterDescription}
|
157
122
|
If you pass the --filter option, it will merge into the filters of the command.
|
@@ -217,16 +182,7 @@ command = command
|
|
217
182
|
.option('-w, --watch', 'Watch the file changes.', parseBoolean)
|
218
183
|
.option('-p, --port <PORT>', 'The port of the server.', Number.parseInt, 8888)
|
219
184
|
|
220
|
-
command = command
|
221
|
-
.option('--ana', 'Enable the bundle analyzer.', parseBoolean)
|
222
|
-
.option('--ana.dir <DIR>', 'The directory of the bundle analyzer.', '.jk-analyses')
|
223
|
-
.option('--ana.mode <MODE>', 'The mode of the bundle analyzer, support "static", "json" and "server".', 'server')
|
224
|
-
.option('--ana.open', 'Open the bundle analyzer in the browser.', parseBoolean)
|
225
|
-
.option(
|
226
|
-
'--ana.size <SIZE>',
|
227
|
-
'The default size of the bundle analyzer, support "stat", "parsed" and "gzip".',
|
228
|
-
'parsed'
|
229
|
-
)
|
185
|
+
command = registerAnalyzerCommandOptions(command)
|
230
186
|
|
231
187
|
command = command
|
232
188
|
.option('-s, --silent', "Don't display logs.", parseBoolean)
|
@@ -282,48 +238,17 @@ command
|
|
282
238
|
[] as string[]
|
283
239
|
)
|
284
240
|
|
285
|
-
const
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
? {
|
291
|
-
dir: options['ana.dir'],
|
292
|
-
mode: options['ana.mode'],
|
293
|
-
open: options['ana.open'],
|
294
|
-
size: options['ana.size']
|
295
|
-
}
|
241
|
+
const shouldCreateServer = [
|
242
|
+
options.ana === true && options['ana.mode'] === 'server'
|
243
|
+
].some(Boolean)
|
244
|
+
const server = shouldCreateServer
|
245
|
+
? createServer(options.port, 'localhost')
|
296
246
|
: undefined
|
297
|
-
if (
|
298
|
-
options.ana
|
299
|
-
&& ![
|
300
|
-
'stat',
|
301
|
-
'parsed',
|
302
|
-
'gzip'
|
303
|
-
].includes(analyzer?.size ?? '')
|
304
|
-
) {
|
305
|
-
throw new Error('The value of `ana.size` must be "stat", "parsed" or "gzip"')
|
306
|
-
}
|
307
|
-
const server = analyzer && createServer(options.port, 'localhost')
|
308
247
|
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
}
|
314
|
-
const anaPaths = new Set<string>()
|
315
|
-
const refreshAnalyzer = async (subPath = '', renderModules = modules) => {
|
316
|
-
if (!(analyzer && server && render)) return
|
317
|
-
const p = `/ana${subPath}`
|
318
|
-
anaPaths.add(p)
|
319
|
-
void server.renderTo(
|
320
|
-
p,
|
321
|
-
await render(renderModules, {
|
322
|
-
title: `Jiek Analyzer - ${subPath}`,
|
323
|
-
mode: analyzer.size as 'stat' | 'parsed' | 'gzip'
|
324
|
-
})
|
325
|
-
)
|
326
|
-
}
|
248
|
+
const {
|
249
|
+
ANALYZER_ENV,
|
250
|
+
refreshAnalyzer
|
251
|
+
} = await useAnalyzer(options, server)
|
327
252
|
|
328
253
|
const { build } = loadConfig()
|
329
254
|
silent = silent ?? build?.silent ?? false
|
@@ -343,7 +268,7 @@ command
|
|
343
268
|
entries = undefined
|
344
269
|
}
|
345
270
|
const env = {
|
346
|
-
|
271
|
+
...ANALYZER_ENV,
|
347
272
|
JIEK_BUILDER: type,
|
348
273
|
JIEK_OUT_DIR: outdir,
|
349
274
|
JIEK_CLEAN: String(!noClean),
|
@@ -388,27 +313,10 @@ command
|
|
388
313
|
.replace(/dist\/rollup.js$/, 'dist/bin/rollup')
|
389
314
|
let i = 0
|
390
315
|
await Promise.all(
|
391
|
-
Object.entries(value).map(async ([
|
316
|
+
Object.entries(value).map(async ([pkgCWD, manifest]) => {
|
392
317
|
if (manifest.name == null) {
|
393
318
|
throw new Error('package.json must have a name field')
|
394
319
|
}
|
395
|
-
if (analyzer) {
|
396
|
-
const anaDir = path.resolve(dir, analyzer.dir)
|
397
|
-
if (!existsSync(anaDir)) {
|
398
|
-
mkdirSync(anaDir, { recursive: true })
|
399
|
-
}
|
400
|
-
const gitIgnorePath = path.resolve(anaDir, '.gitignore')
|
401
|
-
if (!existsSync(gitIgnorePath)) {
|
402
|
-
writeFileSync(gitIgnorePath, '*\n!.gitignore\n')
|
403
|
-
}
|
404
|
-
const npmIgnorePath = path.resolve(anaDir, '.npmignore')
|
405
|
-
if (!existsSync(npmIgnorePath)) {
|
406
|
-
writeFileSync(npmIgnorePath, '*\n')
|
407
|
-
}
|
408
|
-
if (!statSync(anaDir).isDirectory()) {
|
409
|
-
throw new Error(`The directory '${anaDir}' is not a directory.`)
|
410
|
-
}
|
411
|
-
}
|
412
320
|
|
413
321
|
// TODO support auto build child packages in workspaces
|
414
322
|
const escapeManifestName = manifest.name.replace(/^@/g, '').replace(/\//g, '+')
|
@@ -426,7 +334,7 @@ command
|
|
426
334
|
command.push(...passThroughOptions)
|
427
335
|
const child = execaCommand(command.join(' '), {
|
428
336
|
ipc: true,
|
429
|
-
cwd:
|
337
|
+
cwd: pkgCWD,
|
430
338
|
env: {
|
431
339
|
...env,
|
432
340
|
JIEK_NAME: manifest.name,
|
@@ -540,41 +448,18 @@ command
|
|
540
448
|
const {
|
541
449
|
data: {
|
542
450
|
type,
|
543
|
-
path,
|
544
451
|
modules: pkgModules
|
545
452
|
}
|
546
453
|
} = e
|
547
|
-
|
548
|
-
|
454
|
+
void refreshAnalyzer(
|
455
|
+
pkgCWD,
|
456
|
+
pkgModules.map(m => ({
|
549
457
|
...m,
|
458
|
+
type,
|
550
459
|
filename: `${manifest.name}/${m.filename}`,
|
551
460
|
label: `${manifest.name}/${m.label}`
|
552
|
-
}
|
553
|
-
const pushOrReplace = (arr: Module[]) => {
|
554
|
-
const index = arr.findIndex(({ filename }) => filename === newM.filename)
|
555
|
-
if (index === -1) {
|
556
|
-
arr.push(newM)
|
557
|
-
} else {
|
558
|
-
arr[index] = newM
|
559
|
-
}
|
560
|
-
}
|
561
|
-
pushOrReplace(modules)
|
562
|
-
if (type === 'esm') {
|
563
|
-
pushOrReplace(esmModules)
|
564
|
-
}
|
565
|
-
if (type === 'cjs') {
|
566
|
-
pushOrReplace(cjsModules)
|
567
|
-
}
|
568
|
-
})
|
569
|
-
void refreshAnalyzer()
|
570
|
-
void refreshAnalyzer(
|
571
|
-
`/${type}`,
|
572
|
-
{
|
573
|
-
cjs: cjsModules,
|
574
|
-
esm: esmModules
|
575
|
-
}[type]
|
461
|
+
}))
|
576
462
|
)
|
577
|
-
void refreshAnalyzer(`/${type}/${manifest.name}/${path.slice(2)}`, pkgModules)
|
578
463
|
break
|
579
464
|
}
|
580
465
|
case 'debug': {
|
@@ -624,20 +509,7 @@ command
|
|
624
509
|
}
|
625
510
|
} finally {
|
626
511
|
multiBars.stop()
|
627
|
-
let message = 'The build is complete'
|
628
|
-
if (analyzer) {
|
629
|
-
message += ` and the analyzer is running at http://localhost:${options.port}/ana in ${analyzer.mode} mode.\n`
|
630
|
-
message += analyzer.open ? ' The browser will open automatically.\n' : ''
|
631
|
-
if (anaPaths.size > 0) {
|
632
|
-
message += `The analyzer has ${anaPaths.size} pages:\n${
|
633
|
-
Array
|
634
|
-
.from(anaPaths)
|
635
|
-
.map(p => `http://localhost:${options.port}${p}`)
|
636
|
-
.join('\n')
|
637
|
-
}`
|
638
|
-
}
|
639
|
-
}
|
640
512
|
// eslint-disable-next-line no-console
|
641
|
-
!silent && console.log(
|
513
|
+
!silent && console.log('Build complete')
|
642
514
|
}
|
643
515
|
})
|
package/src/rollup/index.ts
CHANGED
@@ -199,9 +199,12 @@ const withMinify = (
|
|
199
199
|
onlyOncePlugins: OutputPluginOption[] = []
|
200
200
|
): OutputOptions[] => {
|
201
201
|
const minify = build?.output?.minify ?? MINIFY_DEFAULT_VALUE
|
202
|
+
|
202
203
|
output.plugins = output.plugins ?? []
|
204
|
+
const notOnlyOncePlugins = [...output.plugins]
|
205
|
+
output.plugins.push(...onlyOncePlugins)
|
206
|
+
|
203
207
|
if (minify === false) {
|
204
|
-
output.plugins.push(...onlyOncePlugins)
|
205
208
|
return [output]
|
206
209
|
}
|
207
210
|
|
@@ -213,11 +216,10 @@ const withMinify = (
|
|
213
216
|
? import('rollup-plugin-swc3').then(({ minify }) => minify(noTypeResolvedMinifyOptions as any))
|
214
217
|
// eslint-disable-next-line ts/no-unsafe-argument
|
215
218
|
: import('@rollup/plugin-terser').then(({ default: minify }) => minify(noTypeResolvedMinifyOptions as any))
|
216
|
-
const notOnlyOncePlugins = output.plugins
|
217
219
|
return minify === 'only-minify'
|
218
220
|
? [{
|
219
221
|
...output,
|
220
|
-
// TODO replace suffix when
|
222
|
+
// TODO replace suffix when publish to npm and the `build.output.minify` is 'only-minify'
|
221
223
|
// TODO resolve dts output file name
|
222
224
|
entryFileNames: chunkInfo =>
|
223
225
|
typeof output.entryFileNames === 'function'
|
@@ -226,6 +228,7 @@ const withMinify = (
|
|
226
228
|
throw new Error('entryFileNames must be a function')
|
227
229
|
})(),
|
228
230
|
plugins: [
|
231
|
+
...output.plugins,
|
229
232
|
...notOnlyOncePlugins,
|
230
233
|
minifyPlugin
|
231
234
|
]
|
@@ -356,7 +359,23 @@ const generateConfigs = (context: ConfigGenerateContext, options: TemplateOption
|
|
356
359
|
const rollupOptions: RollupOptions[] = []
|
357
360
|
|
358
361
|
const commonPlugins: Plugin[] = [
|
359
|
-
nodeResolve({
|
362
|
+
nodeResolve({
|
363
|
+
exportConditions,
|
364
|
+
extensions: [
|
365
|
+
'.js',
|
366
|
+
'.cjs',
|
367
|
+
'.mjs',
|
368
|
+
'.jsx',
|
369
|
+
'.cjsx',
|
370
|
+
'.mjsx',
|
371
|
+
'.ts',
|
372
|
+
'.cts',
|
373
|
+
'.mts',
|
374
|
+
'.tsx',
|
375
|
+
'.ctsx',
|
376
|
+
'.mtsx'
|
377
|
+
]
|
378
|
+
})
|
360
379
|
]
|
361
380
|
if (jsOutput && !WITHOUT_JS) {
|
362
381
|
const sourcemap = typeof options?.output?.sourcemap === 'object'
|
package/src/server.ts
CHANGED
@@ -5,7 +5,15 @@ export const createServer = (port: number, host: string) => {
|
|
5
5
|
app.listen(port, host)
|
6
6
|
const streams = new Map<string, string>()
|
7
7
|
app.use(async (ctx) => {
|
8
|
-
|
8
|
+
let stream = streams.get(ctx.path)
|
9
|
+
if (stream == null) {
|
10
|
+
const maybeKey = streams
|
11
|
+
.keys()
|
12
|
+
.find(p => ctx.path.startsWith(p))
|
13
|
+
stream = maybeKey != null
|
14
|
+
? streams.get(maybeKey)
|
15
|
+
: undefined
|
16
|
+
}
|
9
17
|
if (stream != null) {
|
10
18
|
ctx.body = stream
|
11
19
|
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
import process from 'node:process'
|
2
|
+
|
3
|
+
import { confirm } from '@inquirer/prompts'
|
4
|
+
import { execaCommand } from 'execa'
|
5
|
+
|
6
|
+
import { getWD } from '#~/utils/getWD.ts'
|
7
|
+
|
8
|
+
export async function checkDependency(dependency: string) {
|
9
|
+
try {
|
10
|
+
require.resolve(dependency)
|
11
|
+
} catch {
|
12
|
+
console.error(`The package '${dependency}' is not installed, please install it first.`)
|
13
|
+
const { notWorkspace } = getWD()
|
14
|
+
const command = `pnpm install -${notWorkspace ? '' : 'w'}D ${dependency}`
|
15
|
+
if (await confirm({ message: 'Do you want to install it now?' })) {
|
16
|
+
await execaCommand(command)
|
17
|
+
} else {
|
18
|
+
console.warn(`You can run the command '${command}' to install it manually.`)
|
19
|
+
process.exit(1)
|
20
|
+
}
|
21
|
+
}
|
22
|
+
}
|