Skip to content

Commit 7bcbcd3

Browse files
authored
Merge pull request #19 from electron-vite/v0.11.4
V0.11.4
2 parents e15a3c3 + eea519b commit 7bcbcd3

File tree

4 files changed

+107
-25
lines changed

4 files changed

+107
-25
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.11.4 (2023-01-04)
2+
3+
- 502f7f2 feat: support Pre-Bundling cache #15
4+
15
## 0.11.3 (2022-11-18)
26

37
- cbab7db fix: insert built-in modules to `optimizeDeps.exclude`

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.11.3",
3+
"version": "0.11.4",
44
"description": "Support use Node.js API in Electron-Renderer",
55
"main": "index.mjs",
66
"types": "types",
@@ -32,7 +32,8 @@
3232
"esbuild": "^0.16.11",
3333
"rollup": "^3.8.1",
3434
"typescript": "^4.9.4",
35-
"vite": "^4.0.3"
35+
"vite": "^4.0.3",
36+
"vite-plugin-utils": "^0.3.6"
3637
},
3738
"files": [
3839
"types",

pnpm-lock.yaml

Lines changed: 8 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/optimizer.ts

Lines changed: 92 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import fs from 'node:fs'
22
import path from 'node:path'
3+
import crypto from 'node:crypto'
34
import { createRequire, builtinModules } from 'node:module'
45
import type { Alias, Plugin, UserConfig } from 'vite'
56
import esbuild from 'esbuild'
67
import libEsm from 'lib-esm'
8+
import { COLOURS } from 'vite-plugin-utils/function'
79
import { builtins } from './build-config'
810

911
export type DepOptimizationConfig = {
@@ -27,6 +29,7 @@ const name = 'vite-plugin-electron-renderer:optimizer'
2729

2830
let root: string
2931
let node_modules_path: string
32+
let cache: Cache
3033

3134
export default function optimizer(options: DepOptimizationConfig = {}): Plugin[] | undefined {
3235
const { include, buildOptions } = options
@@ -38,8 +41,7 @@ export default function optimizer(options: DepOptimizationConfig = {}): Plugin[]
3841
config(config) {
3942
root = config.root ? path.resolve(config.root) : process.cwd()
4043
node_modules_path = node_modules(root)
41-
42-
fs.rmSync(path.join(node_modules_path, CACHE_DIR), { recursive: true, force: true })
44+
cache = new Cache(path.join(node_modules_path, CACHE_DIR))
4345

4446
const aliases: Alias[] = [
4547
{
@@ -97,10 +99,10 @@ export default function optimizer(options: DepOptimizationConfig = {}): Plugin[]
9799
continue
98100
}
99101

100-
const pkgId = path.join(node_modules_path, name, 'package.json')
101-
if (fs.existsSync(pkgId)) {
102+
const pkgJson = path.join(node_modules_path, name, 'package.json')
103+
if (fs.existsSync(pkgJson)) {
102104
// bare module
103-
const pkg = cjs_require(pkgId)
105+
const pkg = cjs_require(pkgJson)
104106
if (pkg.type === 'module') {
105107
deps.push({ esm: name })
106108
continue
@@ -109,29 +111,30 @@ export default function optimizer(options: DepOptimizationConfig = {}): Plugin[]
109111
continue
110112
}
111113

112-
const tmp = path.join(node_modules_path, name)
114+
const pkgPath = path.join(node_modules_path, name)
113115
try {
114116
// dirname or filename 🤔
115117
// `foo/bar` or `foo/bar/index.js`
116-
const filename = cjs_require.resolve(tmp)
118+
const filename = cjs_require.resolve(pkgPath)
117119
if (path.extname(filename) === '.mjs') {
118120
deps.push({ esm: name, filename })
119121
continue
120122
}
121123
deps.push({ cjs: name, filename })
122124
continue
123125
} catch (error) {
124-
console.log('Can not resolve path:', tmp)
126+
console.log(COLOURS.red('Can not resolve path:'), pkgPath)
125127
}
126128
}
127129

128130
for (const dep of deps) {
129131
if (!dep.filename) {
130132
const module = (dep.cjs || dep.esm) as string
131133
try {
134+
// TODO: resolve(, [paths condition])
132135
dep.filename = cjs_require.resolve(module)
133136
} catch (error) {
134-
console.log('Can not resolve module:', module)
137+
console.log(COLOURS.red('Can not resolve module:'), module)
135138
}
136139
}
137140
if (!dep.filename) {
@@ -173,9 +176,16 @@ function cjsBundling(args: {
173176
requireId: string
174177
}) {
175178
const { name, require, requireId } = args
179+
const { destpath, destname } = dest(name)
180+
if (cache.checkHash(destname)) return
181+
176182
const { exports } = libEsm({ exports: Object.keys(cjs_require(requireId)) })
177183
const code = `const _M_ = require("${require}");\n${exports}`
178-
writeFile({ name, code })
184+
185+
!fs.existsSync(destpath) && fs.mkdirSync(destpath, { recursive: true })
186+
fs.writeFileSync(destname, code)
187+
cache.writeCache(destname)
188+
console.log(COLOURS.cyan('Pre-bundling:'), COLOURS.yellow(name))
179189
}
180190

181191
async function esmBundling(args: {
@@ -185,6 +195,8 @@ async function esmBundling(args: {
185195
}) {
186196
const { name, entry, buildOptions } = args
187197
const { name_cjs, destname_cjs } = dest(name)
198+
if (cache.checkHash(destname_cjs)) return
199+
188200
return esbuild.build({
189201
entryPoints: [entry],
190202
outfile: destname_cjs,
@@ -199,6 +211,7 @@ async function esmBundling(args: {
199211
...buildOptions,
200212
}).then(result => {
201213
if (!result.errors.length) {
214+
cache.writeCache(destname_cjs)
202215
cjsBundling({
203216
name,
204217
require: `${CACHE_DIR}/${name}/${name_cjs}`,
@@ -209,17 +222,6 @@ async function esmBundling(args: {
209222
})
210223
}
211224

212-
function writeFile(args: {
213-
name: string
214-
code: string
215-
}) {
216-
const { name, code } = args
217-
const { destpath, destname } = dest(name)
218-
!fs.existsSync(destpath) && fs.mkdirSync(destpath, { recursive: true })
219-
fs.writeFileSync(destname, code)
220-
console.log('Pre-bundling:', name)
221-
}
222-
223225
function dest(name: string) {
224226
const destpath = path.join(node_modules_path, CACHE_DIR, name)
225227
const name_js = 'index.js'
@@ -266,3 +268,72 @@ function node_modules(root: string, count = 0): string {
266268
}
267269
// For ts-check
268270
node_modules.p = ''
271+
272+
// ----------------------------------------
273+
274+
export interface ICache {
275+
timestamp?: number
276+
optimized?: {
277+
[filename: string]: {
278+
hash: string
279+
}
280+
}
281+
}
282+
283+
class Cache {
284+
static getHash(filename: string) {
285+
return crypto.createHash('md5').update(fs.readFileSync(filename)).digest('hex')
286+
}
287+
288+
constructor(
289+
public root: string,
290+
public cacheFile = path.join(root, '_metadata.json'),
291+
) {
292+
// TODO: cleanup meta
293+
}
294+
295+
checkHash(filename: string) {
296+
if (!fs.existsSync(filename)) {
297+
return false
298+
}
299+
let hash: string
300+
try {
301+
hash = Cache.getHash(filename)
302+
} catch {
303+
return false
304+
}
305+
const { optimized = {} } = this.readCache()
306+
for (const [file, meta] of Object.entries(optimized)) {
307+
if (filename === file && hash === meta.hash) {
308+
return true
309+
}
310+
}
311+
return false
312+
}
313+
314+
readCache(): ICache {
315+
const cache: ICache = {}
316+
try {
317+
const json = JSON.parse(fs.readFileSync(this.cacheFile, 'utf8'))
318+
Object.assign(cache, { optimized: json.optimized })
319+
} catch { }
320+
return cache
321+
}
322+
323+
writeCache(filename: string) {
324+
if (!fs.existsSync(filename)) {
325+
throw new Error(`${filename} is not exist!`)
326+
}
327+
const { optimized = {} } = this.readCache()
328+
const newCache: ICache = {
329+
timestamp: Date.now(),
330+
optimized: {
331+
...optimized,
332+
[filename]: {
333+
hash: Cache.getHash(filename),
334+
},
335+
},
336+
}
337+
fs.writeFileSync(this.cacheFile, JSON.stringify(newCache, null, 2))
338+
}
339+
}

0 commit comments

Comments
 (0)