@@ -31,9 +31,7 @@ function createWebpackConfig(outputDirName = '', command, argv = {}) {
3131}
3232
3333function convertToManifestPath ( assetSrc , webpackConfig ) {
34- const manifestData = JSON . parse (
35- fs . readFileSync ( path . join ( webpackConfig . outputPath , 'manifest.json' ) , 'utf8' )
36- ) ;
34+ const manifestData = JSON . parse ( readOutputFileContents ( 'manifest.json' , webpackConfig ) ) ;
3735
3836 if ( typeof manifestData [ assetSrc ] === 'undefined' ) {
3937 throw new Error ( `Path ${ assetSrc } not found in manifest!` ) ;
@@ -42,6 +40,26 @@ function convertToManifestPath(assetSrc, webpackConfig) {
4240 return manifestData [ assetSrc ] ;
4341}
4442
43+ function readOutputFileContents ( filename , config ) {
44+ const fullPath = path . join ( config . outputPath , filename ) ;
45+
46+ if ( ! fs . existsSync ( fullPath ) ) {
47+ throw new Error ( `Output file "${ filename } " does not exist.` ) ;
48+ }
49+
50+ return fs . readFileSync ( fullPath , 'utf8' ) ;
51+ }
52+
53+ function getEntrypointData ( config , entryName ) {
54+ const entrypointsData = JSON . parse ( readOutputFileContents ( 'entrypoints.json' , config ) ) ;
55+
56+ if ( typeof entrypointsData . entrypoints [ entryName ] === 'undefined' ) {
57+ throw new Error ( `The entry ${ entryName } was not found!` ) ;
58+ }
59+
60+ return entrypointsData . entrypoints [ entryName ] ;
61+ }
62+
4563describe ( 'Functional tests using webpack' , function ( ) {
4664 // being functional tests, these can take quite long
4765 this . timeout ( 8000 ) ;
@@ -1839,24 +1857,70 @@ module.exports = {
18391857 return config ;
18401858 } ;
18411859
1842- const getMain3Contents = function ( config ) {
1843- const fullPath = path . join ( config . outputPath , 'main3.js' ) ;
1860+ const configA = createSimilarConfig ( false ) ;
1861+ const configB = createSimilarConfig ( true ) ;
1862+
1863+ testSetup . runWebpack ( configA , ( ) => {
1864+ testSetup . runWebpack ( configB , ( ) => {
1865+ const main3Contents = readOutputFileContents ( 'main3.js' , configA ) ;
1866+ const finalMain3Contents = readOutputFileContents ( 'main3.js' , configB ) ;
18441867
1845- if ( ! fs . existsSync ( fullPath ) ) {
1846- throw new Error ( 'Output file "main3.js" does not exist.' ) ;
1868+ if ( finalMain3Contents !== main3Contents ) {
1869+ throw new Error ( `Contents after first compile do not match after second compile: \n\n ${ main3Contents } \n\n versus \n\n ${ finalMain3Contents } \n` ) ;
1870+ }
1871+
1872+ done ( ) ;
1873+ } ) ;
1874+ } ) ;
1875+ } ) ;
1876+
1877+ it ( 'Do not change contents or filenames when more modules require the same split contents' , ( done ) => {
1878+ const createSimilarConfig = function ( includeExtraEntry ) {
1879+ const config = createWebpackConfig ( 'web/build' , 'production' ) ;
1880+ config . addEntry ( 'main1' , [ './js/code_splitting' , 'preact' ] ) ;
1881+ config . addEntry ( 'main3' , [ './js/no_require' , 'preact' ] ) ;
1882+ if ( includeExtraEntry ) {
1883+ config . addEntry ( 'main4' , [ './js/eslint' , 'preact' ] ) ;
1884+ }
1885+ config . setPublicPath ( '/build' ) ;
1886+ config . splitEntryChunks ( ) ;
1887+
1888+ return config ;
1889+ } ;
1890+
1891+ const getSplitVendorJsPath = function ( config ) {
1892+ const entrypointData = getEntrypointData ( config , 'main3' ) ;
1893+
1894+ const splitFiles = entrypointData . js . filter ( filename => {
1895+ return filename !== '/build/runtime.js' && filename !== '/build/main3.js' ;
1896+ } ) ;
1897+
1898+ // sanity check
1899+ if ( splitFiles . length !== 1 ) {
1900+ throw new Error ( `Unexpected number (${ splitFiles . length } ) of split files for main3 entry` ) ;
18471901 }
18481902
1849- return fs . readFileSync ( fullPath , 'utf8' ) ;
1903+ return splitFiles [ 0 ] ;
18501904 } ;
18511905
18521906 const configA = createSimilarConfig ( false ) ;
18531907 const configB = createSimilarConfig ( true ) ;
18541908
18551909 testSetup . runWebpack ( configA , ( ) => {
1856- const main3Contents = getMain3Contents ( configA ) ;
1857-
18581910 testSetup . runWebpack ( configB , ( ) => {
1859- const finalMain3Contents = getMain3Contents ( configB ) ;
1911+ const vendorPath = getSplitVendorJsPath ( configA ) ;
1912+ const finalVendorPath = getSplitVendorJsPath ( configB ) ;
1913+
1914+ // make sure that the filename of the split vendor file didn't change,
1915+ // even though an additional entry is now sharing its contents
1916+ if ( finalVendorPath !== vendorPath ) {
1917+ throw new Error ( `Vendor filename changed! Before ${ vendorPath } and after ${ finalVendorPath } .` ) ;
1918+ }
1919+
1920+ // make sure that, internally, the split chunk name did not change,
1921+ // which would cause the contents of main3 to suddenly change
1922+ const main3Contents = readOutputFileContents ( 'main3.js' , configA ) ;
1923+ const finalMain3Contents = readOutputFileContents ( 'main3.js' , configB ) ;
18601924
18611925 if ( finalMain3Contents !== main3Contents ) {
18621926 throw new Error ( `Contents after first compile do not match after second compile: \n\n ${ main3Contents } \n\n versus \n\n ${ finalMain3Contents } \n` ) ;
0 commit comments