Skip to content

Commit 6748af8

Browse files
authored
V0.13.1 (#36)
* feat: better build types * refactor!: improve Pre-Bundling #35 * log: v0.13.1 * v0.13.1
1 parent f20581e commit 6748af8

File tree

6 files changed

+105
-88
lines changed

6 files changed

+105
-88
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.13.1 (2023-03-21)
2+
3+
893e361 refactor!: improve Pre-Bundling #35
4+
15
## 0.13.0 (2023-03-20)
26

37
#### Break!

README.md

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -85,16 +85,6 @@ export interface RendererOptions {
8585
* @default false
8686
*/
8787
nodeIntegration?: boolean
88-
/**
89-
* Pre-Bundling modules for Electron Renderer process.
90-
*/
91-
optimizer?: {
92-
buildOptions?: import('esbuild').BuildOptions
93-
/**
94-
* Explicitly tell the Pre-Bundling how to work, when value is `false` Vite's default Pre-Bundling will be used.
95-
*/
96-
modules?: { [module: string]: 'commonjs' | 'module' | false }
97-
}
9888
}
9989
```
10090

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "vite-plugin-electron-renderer",
3-
"version": "0.13.0",
3+
"version": "0.13.1",
44
"description": "Support use Node.js API in Electron-Renderer",
55
"main": "index.mjs",
66
"types": "types",
@@ -19,7 +19,8 @@
1919
"license": "MIT",
2020
"scripts": {
2121
"dev": "vite build --watch",
22-
"build": "tsc --emitDeclarationOnly && vite build",
22+
"build": "vite build",
23+
"types": "tsc --emitDeclarationOnly",
2324
"prepublishOnly": "npm run test && npm run build",
2425
"test": "vitest run"
2526
},

src/build-config.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export default function buildConfig(nodeIntegration?: boolean): Plugin[] {
2727
]
2828

2929
modifyAlias(config, aliases)
30+
/*
3031
modifyOptimizeDeps(
3132
config,
3233
nodeIntegration
@@ -36,6 +37,7 @@ export default function buildConfig(nodeIntegration?: boolean): Plugin[] {
3637
'vite-plugin-electron-renderer/builtins/electron',
3738
],
3839
)
40+
*/
3941
},
4042
},
4143
{
@@ -102,6 +104,10 @@ function setOutputFormat(rollupOptions: RollupOptions) {
102104
}
103105
}
104106

107+
/**
108+
* @deprecated better implements in v0.13.1
109+
* @see https://github.com/electron-vite/vite-plugin-electron-renderer/blob/v0.13.1/src/optimizer.ts#L81-L87
110+
*/
105111
function modifyOptimizeDeps(config: UserConfig, exclude: string[]) {
106112
config.optimizeDeps ??= {}
107113
config.optimizeDeps.exclude ??= []

src/optimizer.ts

Lines changed: 54 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,23 @@ import {
66
type Plugin as EsbuildPlugin,
77
} from 'esbuild'
88
import libEsm from 'lib-esm'
9-
import { COLOURS, node_modules as find_node_modules } from 'vite-plugin-utils/function'
9+
import { node_modules as find_node_modules } from 'vite-plugin-utils/function'
1010
import { electronBuiltins, ensureDir } from './utils'
1111

1212
const cjs_require = createRequire(import.meta.url)
13-
const preBundleCjs = 'pre-bundle-cjs'
14-
const preBundleEsm = 'pre-bundle-esm'
13+
const electronNpmCjsNamespace = 'electron:npm-cjs'
14+
const bareImport = /^[\w@].*/
1515
const CACHE_DIR = '.vite-electron-renderer'
1616
let node_modules_path: string
1717
let cache_dir: string
1818

1919
export interface optimizerOptions {
20-
buildOptions?: import('esbuild').BuildOptions
2120
/**
22-
* Explicitly tell the Pre-Bundling how to work, when value is `false` Vite's default Pre-Bundling will be used.
21+
* Explicitly tell the Pre-Bundling how to work.
22+
*
23+
* - `false` Vite's default Pre-Bundling will be used.
2324
*/
24-
modules?: { [module: string]: 'commonjs' | 'module' | false }
25+
resolve?: (args: import('esbuild').OnResolveArgs) => 'commonjs' | 'module' | false | null | undefined | Promise<'commonjs' | 'module' | false | null | undefined>
2526
}
2627

2728
export default function optimizer(options: optimizerOptions, nodeIntegration: boolean): VitePlugin {
@@ -33,6 +34,7 @@ export default function optimizer(options: optimizerOptions, nodeIntegration: bo
3334

3435
config.optimizeDeps ??= {}
3536
config.optimizeDeps.esbuildOptions ??= {}
37+
config.optimizeDeps.esbuildOptions.platform ??= 'node'
3638
config.optimizeDeps.esbuildOptions.plugins ??= []
3739
config.optimizeDeps.esbuildOptions.plugins.push(esbuildPlugin(options))
3840

@@ -66,74 +68,78 @@ export default function optimizer(options: optimizerOptions, nodeIntegration: bo
6668
}
6769

6870
export function esbuildPlugin(options: optimizerOptions): EsbuildPlugin {
69-
const { buildOptions, modules = {} } = options
71+
const { resolve } = options
7072

7173
return {
7274
name: 'vite-plugin-target:optimizer:esbuild',
7375
setup(build) {
74-
build.onResolve({
75-
filter: /^[\w@]/, // bare import
76-
}, async ({ path: id }) => {
76+
// https://github.com/vitejs/vite/blob/v4.2.0/packages/vite/src/node/optimizer/esbuildDepPlugin.ts#L277-L279
77+
const escape = (text: string) =>
78+
`^${text.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')}$`
79+
const filter = new RegExp(electronBuiltins.map(escape).join('|'))
80+
81+
// Electron builtin modules
82+
build.onResolve({ filter }, args => {
83+
return {
84+
path: args.path,
85+
external: true,
86+
}
87+
})
88+
89+
// Third party npm-pkg
90+
build.onResolve({ filter: bareImport }, async args => {
91+
const {
92+
path: id,
93+
namespace,
94+
importer,
95+
} = args
7796
if (electronBuiltins.includes(id)) {
78-
// Builtin modules handled in 'build-config'
97+
// Builtin modules handled in './build-config.ts'
7998
return
8099
}
81-
82-
const userType = modules[id]
83-
if (userType === false) {
84-
// Use Vite's default Pre-Bundling
100+
if (importer.includes('node_modules')) {
101+
return
102+
}
103+
if (id.startsWith('vite-') || namespace.startsWith('vite:')) {
104+
// https://github.com/vitejs/vite/blob/v4.2.0/packages/vite/src/node/optimizer/esbuildDepPlugin.ts#L15-L20
85105
return
86-
} else if (userType === 'commonjs') {
87-
return {
88-
path: id,
89-
namespace: preBundleCjs,
90-
}
91-
} else if (userType === 'module') {
92-
return {
93-
path: id,
94-
namespace: preBundleEsm,
95-
}
96106
}
97107

98108
// ---- Try to detect what type a module is ----
99-
100-
let isCjsModule!: boolean
101-
// Assume a bare module
109+
let moduleType: 'commonjs' | 'module' | undefined
102110
const packageJson = path.join(node_modules_path, id, 'package.json')
103-
// Assume a dirname or filename -> e.g. `foo/bar` or `foo/bar/index.js` 🤔
104-
const modulePath = path.join(node_modules_path, id)
105-
106111
if (fs.existsSync(packageJson)) {
107-
const pkg = cjs_require(packageJson)
108-
if (pkg.type !== 'module') {
109-
isCjsModule = true
110-
}
111-
} else {
112-
try {
113-
const filename = cjs_require.resolve(modulePath)
114-
if (path.extname(filename) !== '.mjs') {
115-
isCjsModule = true
116-
}
117-
} catch (error) {
118-
console.log(COLOURS.red('Can not resolve path:'), modulePath)
119-
}
112+
moduleType = cjs_require(packageJson).type === 'module' ? 'module' : 'commonjs'
120113
}
121114

122-
return {
123-
path: id,
124-
namespace: isCjsModule ? preBundleCjs : preBundleEsm,
115+
const userType = await resolve?.(args)
116+
if (userType === false) {
117+
// Use Vite's default Pre-Bundling
118+
return
119+
}
120+
if (userType === 'commonjs' || userType === 'module') {
121+
moduleType = userType
122+
}
123+
124+
// Only `cjs` modules, especially C/C++ npm-pkg, `es` modules will be use Vite's default Pre-Bundling
125+
if (moduleType === 'commonjs') {
126+
return {
127+
path: id,
128+
namespace: electronNpmCjsNamespace,
129+
}
125130
}
126131
})
127132

128133
build.onLoad({
129134
filter: /.*/,
130-
namespace: preBundleCjs,
135+
namespace: electronNpmCjsNamespace,
131136
}, async ({ path: id }) => {
132137
const { exports } = libEsm({ exports: Object.getOwnPropertyNames(cjs_require(id)) })
133138

134139
return {
135140
contents: `
136141
// Use "__cjs_require" avoid esbuild parse "require"
142+
// TODO: better implements
137143
const __cjs_require = require;
138144
139145
// If a module is a CommonJs, use the "require" loading it can bring better performance.
@@ -143,27 +149,6 @@ ${exports}
143149
`.trim(),
144150
}
145151
})
146-
147-
build.onLoad({
148-
filter: /.*/,
149-
namespace: preBundleEsm,
150-
}, async ({ path: id }) => {
151-
const outfile = path.join(cache_dir, id, 'index.js')
152-
ensureDir(path.dirname(outfile))
153-
154-
await build.esbuild.build({
155-
entryPoints: [id],
156-
outfile,
157-
format: 'esm',
158-
target: 'node14',
159-
bundle: true,
160-
metafile: true,
161-
external: electronBuiltins,
162-
...buildOptions,
163-
})
164-
165-
return { contents: fs.readFileSync(outfile, 'utf8') }
166-
})
167152
},
168153
}
169154
}

vite.config.ts

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
import { defineConfig } from 'vite'
1+
import fs from 'node:fs'
2+
import path from 'node:path'
3+
import { spawn } from 'node:child_process'
24
import { builtinModules } from 'node:module'
5+
import { defineConfig } from 'vite'
36
import pkg from './package.json'
47

58
export default defineConfig({
@@ -25,11 +28,39 @@ export default defineConfig({
2528
},
2629
},
2730
},
28-
plugins: [{
29-
name: 'vite-plugin-builtins',
30-
async config() {
31-
// Runs at dev, build, test
32-
import('./builtins.mjs').then(({ generateBuiltins }) => generateBuiltins())
31+
plugins: [
32+
{
33+
name: 'vite-plugin-builtins',
34+
async config() {
35+
// Runs at dev, build, test
36+
import('./builtins.mjs').then(({ generateBuiltins }) => generateBuiltins())
37+
},
3338
},
34-
}],
39+
{
40+
name: 'generate-types',
41+
async closeBundle() {
42+
removeTypes()
43+
generateTypes()
44+
},
45+
}
46+
],
3547
})
48+
49+
function removeTypes() {
50+
fs.rmSync(path.join(__dirname, 'types'), { recursive: true, force: true })
51+
}
52+
53+
function generateTypes() {
54+
return new Promise(resolve => {
55+
const cp = spawn(
56+
process.platform === 'win32' ? 'npm.cmd' : 'npm',
57+
['run', 'types'],
58+
{ stdio: 'inherit' },
59+
)
60+
cp.on('exit', code => {
61+
!code && console.log('[types]', 'declaration generated')
62+
resolve(code)
63+
})
64+
cp.on('error', process.exit)
65+
})
66+
}

0 commit comments

Comments
 (0)