Skip to content

Commit

Permalink
V0.13.1 (#36)
Browse files Browse the repository at this point in the history
* feat: better build types

* refactor!: improve Pre-Bundling #35

* log: v0.13.1

* v0.13.1
  • Loading branch information
caoxiemeihao authored Mar 21, 2023
1 parent f20581e commit 6748af8
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 88 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.13.1 (2023-03-21)

893e361 refactor!: improve Pre-Bundling #35

## 0.13.0 (2023-03-20)

#### Break!
Expand Down
10 changes: 0 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,16 +85,6 @@ export interface RendererOptions {
* @default false
*/
nodeIntegration?: boolean
/**
* Pre-Bundling modules for Electron Renderer process.
*/
optimizer?: {
buildOptions?: import('esbuild').BuildOptions
/**
* Explicitly tell the Pre-Bundling how to work, when value is `false` Vite's default Pre-Bundling will be used.
*/
modules?: { [module: string]: 'commonjs' | 'module' | false }
}
}
```

Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vite-plugin-electron-renderer",
"version": "0.13.0",
"version": "0.13.1",
"description": "Support use Node.js API in Electron-Renderer",
"main": "index.mjs",
"types": "types",
Expand All @@ -19,7 +19,8 @@
"license": "MIT",
"scripts": {
"dev": "vite build --watch",
"build": "tsc --emitDeclarationOnly && vite build",
"build": "vite build",
"types": "tsc --emitDeclarationOnly",
"prepublishOnly": "npm run test && npm run build",
"test": "vitest run"
},
Expand Down
6 changes: 6 additions & 0 deletions src/build-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export default function buildConfig(nodeIntegration?: boolean): Plugin[] {
]

modifyAlias(config, aliases)
/*
modifyOptimizeDeps(
config,
nodeIntegration
Expand All @@ -36,6 +37,7 @@ export default function buildConfig(nodeIntegration?: boolean): Plugin[] {
'vite-plugin-electron-renderer/builtins/electron',
],
)
*/
},
},
{
Expand Down Expand Up @@ -102,6 +104,10 @@ function setOutputFormat(rollupOptions: RollupOptions) {
}
}

/**
* @deprecated better implements in v0.13.1
* @see https://github.com/electron-vite/vite-plugin-electron-renderer/blob/v0.13.1/src/optimizer.ts#L81-L87
*/
function modifyOptimizeDeps(config: UserConfig, exclude: string[]) {
config.optimizeDeps ??= {}
config.optimizeDeps.exclude ??= []
Expand Down
123 changes: 54 additions & 69 deletions src/optimizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,23 @@ import {
type Plugin as EsbuildPlugin,
} from 'esbuild'
import libEsm from 'lib-esm'
import { COLOURS, node_modules as find_node_modules } from 'vite-plugin-utils/function'
import { node_modules as find_node_modules } from 'vite-plugin-utils/function'
import { electronBuiltins, ensureDir } from './utils'

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

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

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

config.optimizeDeps ??= {}
config.optimizeDeps.esbuildOptions ??= {}
config.optimizeDeps.esbuildOptions.platform ??= 'node'
config.optimizeDeps.esbuildOptions.plugins ??= []
config.optimizeDeps.esbuildOptions.plugins.push(esbuildPlugin(options))

Expand Down Expand Up @@ -66,74 +68,78 @@ export default function optimizer(options: optimizerOptions, nodeIntegration: bo
}

export function esbuildPlugin(options: optimizerOptions): EsbuildPlugin {
const { buildOptions, modules = {} } = options
const { resolve } = options

return {
name: 'vite-plugin-target:optimizer:esbuild',
setup(build) {
build.onResolve({
filter: /^[\w@]/, // bare import
}, async ({ path: id }) => {
// https://github.com/vitejs/vite/blob/v4.2.0/packages/vite/src/node/optimizer/esbuildDepPlugin.ts#L277-L279
const escape = (text: string) =>
`^${text.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')}$`
const filter = new RegExp(electronBuiltins.map(escape).join('|'))

// Electron builtin modules
build.onResolve({ filter }, args => {
return {
path: args.path,
external: true,
}
})

// Third party npm-pkg
build.onResolve({ filter: bareImport }, async args => {
const {
path: id,
namespace,
importer,
} = args
if (electronBuiltins.includes(id)) {
// Builtin modules handled in 'build-config'
// Builtin modules handled in './build-config.ts'
return
}

const userType = modules[id]
if (userType === false) {
// Use Vite's default Pre-Bundling
if (importer.includes('node_modules')) {
return
}
if (id.startsWith('vite-') || namespace.startsWith('vite:')) {
// https://github.com/vitejs/vite/blob/v4.2.0/packages/vite/src/node/optimizer/esbuildDepPlugin.ts#L15-L20
return
} else if (userType === 'commonjs') {
return {
path: id,
namespace: preBundleCjs,
}
} else if (userType === 'module') {
return {
path: id,
namespace: preBundleEsm,
}
}

// ---- Try to detect what type a module is ----

let isCjsModule!: boolean
// Assume a bare module
let moduleType: 'commonjs' | 'module' | undefined
const packageJson = path.join(node_modules_path, id, 'package.json')
// Assume a dirname or filename -> e.g. `foo/bar` or `foo/bar/index.js` 🤔
const modulePath = path.join(node_modules_path, id)

if (fs.existsSync(packageJson)) {
const pkg = cjs_require(packageJson)
if (pkg.type !== 'module') {
isCjsModule = true
}
} else {
try {
const filename = cjs_require.resolve(modulePath)
if (path.extname(filename) !== '.mjs') {
isCjsModule = true
}
} catch (error) {
console.log(COLOURS.red('Can not resolve path:'), modulePath)
}
moduleType = cjs_require(packageJson).type === 'module' ? 'module' : 'commonjs'
}

return {
path: id,
namespace: isCjsModule ? preBundleCjs : preBundleEsm,
const userType = await resolve?.(args)
if (userType === false) {
// Use Vite's default Pre-Bundling
return
}
if (userType === 'commonjs' || userType === 'module') {
moduleType = userType
}

// Only `cjs` modules, especially C/C++ npm-pkg, `es` modules will be use Vite's default Pre-Bundling
if (moduleType === 'commonjs') {
return {
path: id,
namespace: electronNpmCjsNamespace,
}
}
})

build.onLoad({
filter: /.*/,
namespace: preBundleCjs,
namespace: electronNpmCjsNamespace,
}, async ({ path: id }) => {
const { exports } = libEsm({ exports: Object.getOwnPropertyNames(cjs_require(id)) })

return {
contents: `
// Use "__cjs_require" avoid esbuild parse "require"
// TODO: better implements
const __cjs_require = require;
// If a module is a CommonJs, use the "require" loading it can bring better performance.
Expand All @@ -143,27 +149,6 @@ ${exports}
`.trim(),
}
})

build.onLoad({
filter: /.*/,
namespace: preBundleEsm,
}, async ({ path: id }) => {
const outfile = path.join(cache_dir, id, 'index.js')
ensureDir(path.dirname(outfile))

await build.esbuild.build({
entryPoints: [id],
outfile,
format: 'esm',
target: 'node14',
bundle: true,
metafile: true,
external: electronBuiltins,
...buildOptions,
})

return { contents: fs.readFileSync(outfile, 'utf8') }
})
},
}
}
45 changes: 38 additions & 7 deletions vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { defineConfig } from 'vite'
import fs from 'node:fs'
import path from 'node:path'
import { spawn } from 'node:child_process'
import { builtinModules } from 'node:module'
import { defineConfig } from 'vite'
import pkg from './package.json'

export default defineConfig({
Expand All @@ -25,11 +28,39 @@ export default defineConfig({
},
},
},
plugins: [{
name: 'vite-plugin-builtins',
async config() {
// Runs at dev, build, test
import('./builtins.mjs').then(({ generateBuiltins }) => generateBuiltins())
plugins: [
{
name: 'vite-plugin-builtins',
async config() {
// Runs at dev, build, test
import('./builtins.mjs').then(({ generateBuiltins }) => generateBuiltins())
},
},
}],
{
name: 'generate-types',
async closeBundle() {
removeTypes()
generateTypes()
},
}
],
})

function removeTypes() {
fs.rmSync(path.join(__dirname, 'types'), { recursive: true, force: true })
}

function generateTypes() {
return new Promise(resolve => {
const cp = spawn(
process.platform === 'win32' ? 'npm.cmd' : 'npm',
['run', 'types'],
{ stdio: 'inherit' },
)
cp.on('exit', code => {
!code && console.log('[types]', 'declaration generated')
resolve(code)
})
cp.on('error', process.exit)
})
}

0 comments on commit 6748af8

Please sign in to comment.