Skip to content

Commit

Permalink
fix: differentiate between rel=preload and rel=stylesheet for CSS files
Browse files Browse the repository at this point in the history
  • Loading branch information
bgoscinski committed Sep 13, 2022
1 parent 82dea8e commit d199621
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 22 deletions.
15 changes: 8 additions & 7 deletions packages/vite/src/node/plugins/importAnalysisBuild.ts
Expand Up @@ -65,13 +65,7 @@ function preload(
return baseModule()
}

const absoluteUrls = new Set<string>()
const links = document.getElementsByTagName('link')
for (let i = links.length - 1; i >= 0; i--) {
// The `links[i].href` is an absolute URL thanks to browser doing the work
// for us. See https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#reflecting-content-attributes-in-idl-attributes:idl-domstring-5
absoluteUrls.add(links[i].href)
}

return Promise.all(
deps.map((dep) => {
Expand All @@ -89,7 +83,14 @@ function preload(
if (isBaseRelative) {
// When isBaseRelative is true then we have `importerUrl` and `dep` is
// already converted to an absolute URL by the `assetsURL` function
if (absoluteUrls.has(dep)) return
for (let i = links.length - 1; i >= 0; i--) {
const link = links[i]
// The `links[i].href` is an absolute URL thanks to browser doing the work
// for us. See https://html.spec.whatwg.org/multipage/common-dom-interfaces.html#reflecting-content-attributes-in-idl-attributes:idl-domstring-5
if (link.href === dep && (!isCss || link.rel === 'stylesheet')) {
return
}
}
} else if (document.querySelector(`link[href="${dep}"]${cssSelector}`)) {
return
}
Expand Down
65 changes: 50 additions & 15 deletions playground/css-dynamic-import/__tests__/css-dynamic-import.spec.ts
Expand Up @@ -12,7 +12,8 @@ const getConfig = (base: string): InlineConfig => ({
base,
root: rootDir,
logLevel: 'silent',
preview: { port: ports['css/dynamic-import'] }
preview: { port: ports['css/dynamic-import'] },
build: { assetsInlineLimit: 0 }
})

async function withBuild(base: string, fn: () => Promise<void>) {
Expand Down Expand Up @@ -42,14 +43,17 @@ async function withServe(base: string, fn: () => Promise<void>) {
}
}

async function getChunks() {
async function getLinks() {
const links = await page.$$('link')
const hrefs = await Promise.all(links.map((l) => l.evaluate((el) => el.href)))
return hrefs.map((href) => {
// drop hash part from the file name
const [_, name, ext] = href.match(/assets\/([a-z]+)\..*?\.(.*)$/)
return `${name}.${ext}`
})
return await Promise.all(
links.map((handle) => {
return handle.evaluate((link) => ({
pathname: new URL(link.href).pathname,
rel: link.rel,
as: link.as
}))
})
)
}

baseOptions.forEach(({ base, label }) => {
Expand All @@ -60,12 +64,37 @@ baseOptions.forEach(({ base, label }) => {
await page.waitForSelector('.loaded', { state: 'attached' })

expect(await getColor('.css-dynamic-import')).toBe('green')
expect(await getChunks()).toEqual([
'index.css',
'dynamic.js',
'dynamic.css',
'static.js',
'index.js'
expect(await getLinks()).toEqual([
{
pathname: expect.stringMatching(/^\/assets\/index\..+\.css$/),
rel: 'stylesheet',
as: ''
},
{
pathname: expect.stringMatching(/^\/assets\/dynamic\..+\.css$/),
rel: 'preload',
as: 'style'
},
{
pathname: expect.stringMatching(/^\/assets\/dynamic\..+\.js$/),
rel: 'modulepreload',
as: 'script'
},
{
pathname: expect.stringMatching(/^\/assets\/dynamic\..+\.css$/),
rel: 'stylesheet',
as: ''
},
{
pathname: expect.stringMatching(/^\/assets\/static\..+\.js$/),
rel: 'modulepreload',
as: 'script'
},
{
pathname: expect.stringMatching(/^\/assets\/index\..+\.js$/),
rel: 'modulepreload',
as: 'script'
}
])
})
}
Expand All @@ -79,7 +108,13 @@ baseOptions.forEach(({ base, label }) => {

expect(await getColor('.css-dynamic-import')).toBe('green')
// in serve there is no preloading
expect(await getChunks()).toEqual([])
expect(await getLinks()).toEqual([
{
pathname: '/dynamic.css',
rel: 'preload',
as: 'style'
}
])
})
}
)
Expand Down
5 changes: 5 additions & 0 deletions playground/css-dynamic-import/index.js
@@ -1,5 +1,10 @@
import './static.js'

const link = document.head.appendChild(document.createElement('link'))
link.rel = 'preload'
link.as = 'style'
link.href = new URL('./dynamic.css', import.meta.url).href

import('./dynamic.js').then(async ({ lazyLoad }) => {
await lazyLoad()
})

0 comments on commit d199621

Please sign in to comment.