diff --git a/packages/component/src/loadableReady.js b/packages/component/src/loadableReady.js index 11e8dedf..689ff37d 100644 --- a/packages/component/src/loadableReady.js +++ b/packages/component/src/loadableReady.js @@ -56,7 +56,9 @@ export default function loadableReady( function checkReadyState() { if ( requiredChunks.every(chunk => - loadedChunks.some(([chunks]) => chunks.indexOf(chunk) > -1), + loadedChunks.some(([chunks]) => + chunks.some(c => String(c) === String(chunk)), + ), ) ) { if (!resolved) { diff --git a/packages/component/src/loadableReady.test.js b/packages/component/src/loadableReady.test.js new file mode 100644 index 00000000..7726ab8f --- /dev/null +++ b/packages/component/src/loadableReady.test.js @@ -0,0 +1,63 @@ +/* eslint-disable no-underscore-dangle */ +import 'regenerator-runtime/runtime' +import loadableReady from './loadableReady' +import { LOADABLE_SHARED } from './shared' + +beforeEach(() => { + document.body.innerHTML = '' + delete window.__LOADABLE_LOADED_CHUNKS__ + LOADABLE_SHARED.initialChunks = {} +}) + +function setupRequiredChunks(requiredChunks, namedChunks = []) { + const id = '__LOADABLE_REQUIRED_CHUNKS__' + const script = document.createElement('script') + script.id = id + script.type = 'application/json' + script.textContent = JSON.stringify(requiredChunks) + document.body.appendChild(script) + + const extScript = document.createElement('script') + extScript.id = `${id}_ext` + extScript.type = 'application/json' + extScript.textContent = JSON.stringify({ namedChunks }) + document.body.appendChild(extScript) +} + +describe('loadableReady', () => { + it('should resolve when all string chunks are loaded', async () => { + setupRequiredChunks(['letters-A']) + window.__LOADABLE_LOADED_CHUNKS__ = [[['letters-A'], []]] + + const done = jest.fn() + await loadableReady(done) + expect(done).toHaveBeenCalled() + }) + + it('should resolve when required chunks are numeric and loaded chunks are numeric', async () => { + setupRequiredChunks([1, 2]) + window.__LOADABLE_LOADED_CHUNKS__ = [[[1, 2], []]] + + const done = jest.fn() + await loadableReady(done) + expect(done).toHaveBeenCalled() + }) + + it('should resolve when required chunks are string but loaded chunks are numeric', async () => { + setupRequiredChunks(['1', '2']) + window.__LOADABLE_LOADED_CHUNKS__ = [[[1, 2], []]] + + const done = jest.fn() + await loadableReady(done) + expect(done).toHaveBeenCalled() + }) + + it('should resolve when required chunks are numeric but loaded chunks are string', async () => { + setupRequiredChunks([1, 2]) + window.__LOADABLE_LOADED_CHUNKS__ = [[['1', '2'], []]] + + const done = jest.fn() + await loadableReady(done) + expect(done).toHaveBeenCalled() + }) +}) diff --git a/packages/server/src/ChunkExtractor.js b/packages/server/src/ChunkExtractor.js index 80e95f2b..3f487869 100644 --- a/packages/server/src/ChunkExtractor.js +++ b/packages/server/src/ChunkExtractor.js @@ -225,7 +225,9 @@ class ChunkExtractor { } getChunkInfo(chunkId) { - const chunkInfo = this.stats.chunks.find(chunk => chunk.id === chunkId) + const chunkInfo = this.stats.chunks.find( + chunk => String(chunk.id) === String(chunkId), + ) invariant(chunkInfo, `cannot find chunk (chunkId: ${chunkId}) in stats`) return chunkInfo } @@ -300,15 +302,17 @@ class ChunkExtractor { const chunkGroup = this.getChunkGroup(chunk) // ignore chunk that only contains css files. - return chunkGroup.chunks.filter(chunkId => { - const chunkInfo = this.getChunkInfo(chunkId) + return chunkGroup.chunks + .map(chunkId => String(chunkId)) + .filter(chunkId => { + const chunkInfo = this.getChunkInfo(chunkId) - if (!chunkInfo) { - return false - } + if (!chunkInfo) { + return false + } - return checkIfChunkIncludesJs(chunkInfo) - }) + return checkIfChunkIncludesJs(chunkInfo) + }) } if (Array.isArray(chunks)) { diff --git a/packages/server/src/ChunkExtractor.test.js b/packages/server/src/ChunkExtractor.test.js index 2551235c..ee1625c7 100644 --- a/packages/server/src/ChunkExtractor.test.js +++ b/packages/server/src/ChunkExtractor.test.js @@ -929,4 +929,27 @@ describe('ChunkExtrator', () => { expect(x.hello).toBe('hello') }) }) + + describe('numeric chunk ids', () => { + const numericIdStats = { + ...stats, + chunks: [{ id: 0, files: ['main.css', 'main.js'] }], + } + + it('#getChunkInfo should find chunks with numeric ids', () => { + const ext = new ChunkExtractor({ + stats: numericIdStats, + outputPath: targetPath, + }) + expect(ext.getChunkInfo(0).id).toBe(0) + }) + + it('#getChunkInfo should find numeric chunk when given string id', () => { + const ext = new ChunkExtractor({ + stats: numericIdStats, + outputPath: targetPath, + }) + expect(ext.getChunkInfo('0').id).toBe(0) + }) + }) })