feat: support import rewriting in index.html

This commit is contained in:
Evan You 2020-04-21 18:06:55 -04:00
parent a307eeb056
commit 4ed433a165
2 changed files with 33 additions and 9 deletions

View File

@ -10,16 +10,12 @@ Create the following files:
```html
<div id="app"></div>
<script type="module" src="/main.js"></script>
```
**main.js**
```js
<script type="module">
import { createApp } from 'vue'
import Comp from './Comp.vue'
createApp(Comp).mount('#app')
</script>
```
**Comp.vue**
@ -54,9 +50,7 @@ Go to `http://localhost:3000`, edit the `.vue` file to see changes hot-updated i
- The server intercepts requests to `*.vue` files, compiles them on the fly, and sends them back as JavaScript.
- Imports to npm packages inside `.js` files are re-written on the fly to point to locally installed files (only packages that provide ES module builds will work - `"module"` field will be used if present in `package.json`). There is also plans to integrate with [Snowpack](https://www.snowpack.dev/) to leverage its `web_modules`.
Note this rewrite currently doesn't work in `index.html`, but can probably be made to.
- Imports to npm packages inside `.js` files (and in `<script>` of `index.html`) are re-written on the fly to point to locally installed files (only packages that provide ES module builds will work - `"module"` field will be used if present in `package.json`). There is also plans to integrate with [Snowpack](https://www.snowpack.dev/) to leverage its `web_modules`.
- For libraries that provide ES modules builds that work in browsers, you can also directly import them from a CDN.

View File

@ -4,11 +4,28 @@ import path from 'path'
import { promises as fs, createReadStream } from 'fs'
import resolve from 'resolve-from'
import { rewrite } from '../moduleRewriter'
import { Readable } from 'stream'
const idToFileMap = new Map()
const fileToIdMap = new Map()
export const moduleResolverMiddleware: Middleware = ({ cwd, app }) => {
// rewrite <script> imports in index.html
app.use(async (ctx, next) => {
await next()
if (ctx.url === '/index.html') {
const html = ctx.body.pipe ? await readStream(ctx.body) : String(ctx.body)
ctx.body = html.replace(
/(<script\b[^>]*>)([\s\S]*?)<\/script>/gm,
(_, openTag, script) => {
return `${openTag}${rewrite(script)}</script>`
}
)
console.log(ctx.body)
}
})
// rewrite imports in all js files to /__modules/:id
app.use(async (ctx, next) => {
if (!ctx.path.endsWith('.js')) {
return next()
@ -26,6 +43,7 @@ export const moduleResolverMiddleware: Middleware = ({ cwd, app }) => {
}
})
// handle /__modules/:id requests
const moduleRE = /^\/__modules\//
app.use(async (ctx, next) => {
if (!moduleRE.test(ctx.path)) {
@ -94,3 +112,15 @@ export const moduleResolverMiddleware: Middleware = ({ cwd, app }) => {
}
})
}
async function readStream(stream: Readable): Promise<string> {
return new Promise((resolve, reject) => {
let res = ''
stream
.on('data', (chunk) => (res += chunk))
.on('error', reject)
.on('end', () => {
resolve(res)
})
})
}