Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: importmap should insert before module preload link #11492

Merged
merged 3 commits into from Jan 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
24 changes: 17 additions & 7 deletions packages/vite/src/node/plugins/html.ts
Expand Up @@ -50,6 +50,12 @@ const importMapRE =
/[ \t]*<script[^>]*type\s*=\s*(?:"importmap"|'importmap'|importmap)[^>]*>.*?<\/script>/is
const moduleScriptRE =
/[ \t]*<script[^>]*type\s*=\s*(?:"module"|'module'|module)[^>]*>/i
const modulePreloadLinkRE =
/[ \t]*<link[^>]*rel\s*=\s*(?:"modulepreload"|'modulepreload'|modulepreload)[\s\S]*?\/>/i
const importMapAppendRE = new RegExp(
[moduleScriptRE, modulePreloadLinkRE].map((r) => r.source).join('|'),
'i',
)

export const isHTMLProxy = (id: string): boolean => htmlProxyRE.test(id)

Expand Down Expand Up @@ -891,17 +897,17 @@ export function preImportMapHook(
const importMapIndex = html.match(importMapRE)?.index
if (importMapIndex === undefined) return

const moduleScriptIndex = html.match(moduleScriptRE)?.index
if (moduleScriptIndex === undefined) return
const importMapAppendIndex = html.match(importMapAppendRE)?.index
if (importMapAppendIndex === undefined) return

if (moduleScriptIndex < importMapIndex) {
if (importMapAppendIndex < importMapIndex) {
const relativeHtml = normalizePath(
path.relative(config.root, ctx.filename),
)
config.logger.warnOnce(
colors.yellow(
colors.bold(
`(!) <script type="importmap"> should come before <script type="module"> in /${relativeHtml}`,
`(!) <script type="importmap"> should come before <script type="module"> and <link rel="modulepreload"> in /${relativeHtml}`,
),
),
)
Expand All @@ -910,19 +916,23 @@ export function preImportMapHook(
}
fi3ework marked this conversation as resolved.
Show resolved Hide resolved

/**
* Move importmap before the first module script
* Move importmap before the first module script and modulepreload link
*/
export function postImportMapHook(): IndexHtmlTransformHook {
return (html) => {
if (!moduleScriptRE.test(html)) return
if (!importMapAppendRE.test(html)) return

let importMap: string | undefined
html = html.replace(importMapRE, (match) => {
importMap = match
fi3ework marked this conversation as resolved.
Show resolved Hide resolved
return ''
})

if (importMap) {
html = html.replace(moduleScriptRE, (match) => `${importMap}\n${match}`)
html = html.replace(
importMapAppendRE,
(match) => `${importMap}\n${match}`,
)
}

return html
Expand Down
19 changes: 13 additions & 6 deletions playground/html/__tests__/html.spec.ts
Expand Up @@ -251,12 +251,6 @@ describe.runIf(isServe)('invalid', () => {
})
})

test('importmap', () => {
expect(browserLogs).not.toContain(
'An import map is added after module script load was triggered.',
)
})

describe('Valid HTML', () => {
test('valid HTML is parsed', async () => {
await page.goto(viteTestUrl + '/valid.html')
Expand All @@ -267,3 +261,16 @@ describe('Valid HTML', () => {
expect(await getColor('#duplicated-attrs')).toBe('green')
})
})

describe('importmap', () => {
beforeAll(async () => {
await page.goto(viteTestUrl + '/importmapOrder.html')
})

// Should put this test at the end to get all browser logs above
test('importmap should be prepended', async () => {
expect(browserLogs).not.toContain(
'An import map is added after module script load was triggered.',
)
})
})
14 changes: 14 additions & 0 deletions playground/html/importmapOrder.html
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<script type="importmap">
{
"imports": {
"some-pkg": "url-of-pkg"
}
}
</script>
<link rel="modulepreload" href="url-of-pkg" />
<script type="module" src="/main.js"></script>
</head>
</html>
5 changes: 4 additions & 1 deletion playground/html/vite.config.js
Expand Up @@ -28,6 +28,7 @@ module.exports = {
),
linkProps: resolve(__dirname, 'link-props/index.html'),
valid: resolve(__dirname, 'valid.html'),
importmapOrder: resolve(__dirname, 'importmapOrder.html'),
},
},
},
Expand Down Expand Up @@ -168,7 +169,9 @@ ${
},
{
name: 'head-prepend-importmap',
transformIndexHtml() {
transformIndexHtml(_, ctx) {
if (ctx.path.includes('importmapOrder')) return

return [
{
tag: 'script',
Expand Down