Skip to content

Commit

Permalink
feat: add esbuid-bundle plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
hardfist committed Aug 21, 2021
1 parent 632a50a commit 5bde264
Show file tree
Hide file tree
Showing 14 changed files with 1,533 additions and 14 deletions.
12 changes: 12 additions & 0 deletions packages/playground/esbuild-bundle/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite App</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
27 changes: 27 additions & 0 deletions packages/playground/esbuild-bundle/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "esbuild-bundle",
"version": "0.0.0",
"scripts": {
"dev": "vite",
"build": "vite build",
"build:esbuild": "VITE_ESBUILD_BUNDLE=true vite build",
"serve": "vite preview"
},
"dependencies": {
"react": "^17.0.0",
"react-dom": "^17.0.0",
"three": "0.131.3",
"lodash": "^4.17.21",
"rxjs": "*",
"antd": "*",
"@material-ui/core": "*"
},
"devDependencies": {
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"@vitejs/plugin-react-refresh": "^1.3.1",
"typescript": "~4.2.4",
"vite": "^2.1.5",
"vite-esbuild-bundle-plugin": "*"
}
}
42 changes: 42 additions & 0 deletions packages/playground/esbuild-bundle/src/App.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
.App {
text-align: center;
}

.App-logo {
height: 40vmin;
pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}

.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}

.App-link {
color: #61dafb;
}

@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

button {
font-size: calc(10px + 2vmin);
}
53 changes: 53 additions & 0 deletions packages/playground/esbuild-bundle/src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import React, { useState, useEffect } from 'react'
import './App.css'
import * as three from 'three'
import * as lodash from 'lodash'
import * as rx from 'rxjs'
import * as antd from 'antd'
import * as material from '@material-ui/core'
console.log('big lib', three, lodash, rx, antd)

function App() {
const [count, setCount] = useState(0)
useEffect(async () => {
const result = await import('./answer')
console.log('result:', result.answer)
}, [])
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>Hello Vite + React!</p>
<p>
<button type="button" onClick={() => setCount((count) => count + 1)}>
count is: {count}
</button>
</p>
<p>
Edit <code>App.tsx</code> and save to test HMR updates.
</p>
<p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
{' | '}
<a
className="App-link"
href="https://vitejs.dev/guide/features.html"
target="_blank"
rel="noopener noreferrer"
>
Vite Docs
</a>
</p>
</header>
</div>
)
}

export default App
1 change: 1 addition & 0 deletions packages/playground/esbuild-bundle/src/answer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const answer = 42
13 changes: 13 additions & 0 deletions packages/playground/esbuild-bundle/src/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
11 changes: 11 additions & 0 deletions packages/playground/esbuild-bundle/src/main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react'
import ReactDOM from 'react-dom'
import './index.css'
import App from './App'

ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
)
1 change: 1 addition & 0 deletions packages/playground/esbuild-bundle/src/vite-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// <reference types="vite/client" />
19 changes: 19 additions & 0 deletions packages/playground/esbuild-bundle/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"compilerOptions": {
"target": "ESNext",
"lib": ["DOM", "DOM.Iterable", "ESNext"],
"allowJs": false,
"skipLibCheck": false,
"esModuleInterop": false,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "ESNext",
"moduleResolution": "Node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react"
},
"include": ["./src"]
}
10 changes: 10 additions & 0 deletions packages/playground/esbuild-bundle/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { defineConfig, Plugin, ResolvedConfig } from 'vite'
import { viteEsbuildBundlePlugin } from 'vite-esbuild-bundle-plugin'

// https://vitejs.dev/config/
export default defineConfig({
build: {
minify: false
},
plugins: [process.env.VITE_ESBUILD_BUNDLE && viteEsbuildBundlePlugin()]
})
19 changes: 19 additions & 0 deletions packages/plugin-esbuild-bundle/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "vite-esbuild-bundle-plugin",
"version": "1.0.0",
"description": "",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"build": "tsc",
"test": "echo \"Error: no test specified\" && exit 1"
},
"devDependencies": {
"vite": "^2.1.5",
"esbuild": "0.12.22",
"@types/node": "~15.12.4"
},
"keywords": [],
"author": "",
"license": "ISC"
}
128 changes: 128 additions & 0 deletions packages/plugin-esbuild-bundle/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
import type { Plugin, ResolvedConfig } from 'vite'
import { build } from 'esbuild'
import path from 'path'

export function viteEsbuildBundlePlugin(): Plugin {
let config: ResolvedConfig
const facadeChunks = []
return {
name: 'vite:esbuild',
enforce: 'pre',
apply: 'build',
config(cfg) {
return {
build: {
cssCodeSplit: false,
commonjsOptions: {
include: ['']
}
}
}
},
configResolved(cfg) {
config = cfg
},
async resolveId(source, importer) {
const realId = await this.resolve(source, importer, {
skipSelf: true
})
if (realId?.id.includes('node_modules')) {
return {
id: source,
external: true
}
}
return undefined
},
async generateBundle(options, chunkMap) {
const entryPoints = {}

for (const [file, chunk] of Object.entries(chunkMap)) {
if (file.endsWith('.js') && chunk.type === 'chunk') {
entryPoints[path.resolve(config.root, file)] = chunk
if (chunk.isEntry) {
facadeChunks.push(file)
}
}
}
/* eslint-disable */
const context = this
/* eslint-enable */
const result = await build({
entryPoints: Object.keys(entryPoints),
write: false,
absWorkingDir: __dirname,
bundle: true,
outdir: '/assets',
format: 'esm',
allowOverwrite: true,
splitting: true,
plugins: [
{
name: 'memfs',
setup(build) {
build.onResolve({ filter: /.*/ }, async (args) => {
const realPath = path.resolve(args.resolveDir, args.path)
if (entryPoints[realPath]) {
return {
path: realPath
}
} else {
const result = await context.resolve(
args.path,
args.importer,
{
skipSelf: true
}
)
return {
path: result.id
}
}
})
build.onLoad({ filter: /.*/ }, (args) => {
const res = entryPoints[args.path]
if (res) {
return {
contents: entryPoints[args.path].code,
resolveDir: path.dirname(args.path)
}
}
})
}
}
]
})
for (const output of result.outputFiles) {
const fileName = path.relative('/', output.path)
const formatedContent = output.text.replace(
'"__VITE_PRELOAD__"',
'void 0'
)
/**
* rollup not support emitChunk in generate bundle,which is hard to deal with
* so we have to use transformIndexHtml to handle script injection
* see https://github.com/rollup/rollup/issues/4210
*/
this.emitFile({
type: 'asset',
fileName: fileName,
source: formatedContent
})
}
},
async transformIndexHtml(html) {
return [
// js entry chunk for this page
{
tag: 'script',
attrs: {
type: 'module',
crossorigin: true,
src: facadeChunks[0]
}
}
]
}
} as Plugin
}
11 changes: 11 additions & 0 deletions packages/plugin-esbuild-bundle/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"compilerOptions": {
"declaration": true,
"outDir": "dist",
"esModuleInterop": true,
"module": "CommonJS",
"moduleResolution": "node",
"target": "ESNext"
},
"include": ["src"]
}
Loading

0 comments on commit 5bde264

Please sign in to comment.