Skip to content

Commit a3a4c2e

Browse files
committed
Gracefully handle missing directory separators in publicPath
1 parent 309f8dd commit a3a4c2e

File tree

3 files changed

+53
-1
lines changed

3 files changed

+53
-1
lines changed

src/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const defaultOptions = require('./lib/default-options')
1919
const determineAsValue = require('./lib/determine-as-value')
2020
const doesChunkBelongToHTML = require('./lib/does-chunk-belong-to-html')
2121
const extractChunks = require('./lib/extract-chunks')
22+
const joinPaths = require('./lib/join-paths')
2223

2324
class PreloadPlugin {
2425
constructor (options) {
@@ -76,7 +77,7 @@ class PreloadPlugin {
7677
? webpackPublicPath : ''
7778
: webpackPublicPath || ''
7879
for (const file of sortedFilteredFiles) {
79-
const href = `${publicPath}${file}`
80+
const href = joinPaths(publicPath, file)
8081

8182
const attributes = {
8283
href,

src/lib/join-paths.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
2+
function joinPaths (...segments) {
3+
let joined = segments
4+
.map((segment) => segment.replace(/^\/|\/$/g, ''))
5+
.filter(Boolean)
6+
.join('/')
7+
8+
const first = segments[0]
9+
const last = segments[segments.length - 1]
10+
11+
if (first[0] === '/') joined = `/${joined}`
12+
if (last[last.length - 1] === '/') joined = `${joined}/`
13+
14+
return joined
15+
}
16+
17+
module.exports = joinPaths

test/spec.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,40 @@ module.exports = ({
133133
})
134134
compiler.outputFileSystem = fs
135135
})
136+
137+
it('should gracefully handle missing publicPath separators', function (done) {
138+
const fs = new MemoryFileSystem()
139+
const compiler = webpack({
140+
entry: {
141+
js: path.join(__dirname, 'fixtures', 'file.js')
142+
},
143+
output: {
144+
path: OUTPUT_DIR,
145+
filename: 'bundle.js',
146+
chunkFilename: 'chunk.[chunkhash].js',
147+
publicPath: '/a'
148+
},
149+
plugins: [
150+
new HtmlWebpackPlugin(),
151+
new PreloadPlugin()
152+
]
153+
}, function (err, result) {
154+
expect(err).toBeFalsy(err)
155+
expect(result.compilation.errors.length).toBe(0,
156+
result.compilation.errors.join('\n=========\n'))
157+
158+
const html = fs.readFileSync(path.join(OUTPUT_DIR, 'index.html'), 'utf-8')
159+
const dom = new JSDOM(html)
160+
161+
const links = dom.window.document.head.querySelectorAll('link')
162+
expect(links.length).toBe(1)
163+
expect(links[0].getAttribute('rel')).toBe('preload')
164+
expect(links[0].getAttribute('href')).toMatch(new RegExp('^/a/chunk\\.'))
165+
166+
done()
167+
})
168+
compiler.outputFileSystem = fs
169+
})
136170
})
137171

138172
describe(`${descriptionPrefix} When passed non-async chunks, it`, function () {

0 commit comments

Comments
 (0)