@@ -3,14 +3,107 @@ import { fileURLToPath } from 'node:url'
3
3
import colors from 'picocolors'
4
4
import type { Logger } from 'vite'
5
5
import { describe , expect , test , vi } from 'vitest'
6
- import type { OutputOptions } from 'rollup'
6
+ import type { OutputChunk , OutputOptions , RollupOutput } from 'rollup'
7
7
import type { LibraryFormats , LibraryOptions } from '../build'
8
- import { resolveBuildOutputs , resolveLibFilename } from '../build'
8
+ import { build , resolveBuildOutputs , resolveLibFilename } from '../build'
9
9
import { createLogger } from '../logger'
10
10
11
11
const __dirname = resolve ( fileURLToPath ( import . meta. url ) , '..' )
12
12
13
13
type FormatsToFileNames = [ LibraryFormats , string ] [ ]
14
+
15
+ describe ( 'build' , ( ) => {
16
+ test ( 'file hash should change when css changes for dynamic entries' , async ( ) => {
17
+ const buildProject = async ( cssColor : string ) => {
18
+ return ( await build ( {
19
+ root : resolve ( __dirname , 'packages/build-project' ) ,
20
+ logLevel : 'silent' ,
21
+ build : {
22
+ write : false ,
23
+ } ,
24
+ plugins : [
25
+ {
26
+ name : 'test' ,
27
+ resolveId ( id ) {
28
+ if (
29
+ id === 'entry.js' ||
30
+ id === 'subentry.js' ||
31
+ id === 'foo.css'
32
+ ) {
33
+ return '\0' + id
34
+ }
35
+ } ,
36
+ load ( id ) {
37
+ if ( id === '\0entry.js' ) {
38
+ return `window.addEventListener('click', () => { import('subentry.js') });`
39
+ }
40
+ if ( id === '\0subentry.js' ) {
41
+ return `import 'foo.css'`
42
+ }
43
+ if ( id === '\0foo.css' ) {
44
+ return `.foo { color: ${ cssColor } }`
45
+ }
46
+ } ,
47
+ } ,
48
+ ] ,
49
+ } ) ) as RollupOutput
50
+ }
51
+ const result = await Promise . all ( [
52
+ buildProject ( 'red' ) ,
53
+ buildProject ( 'blue' ) ,
54
+ ] )
55
+ assertOutputHashContentChange ( result [ 0 ] , result [ 1 ] )
56
+ } )
57
+
58
+ test ( 'file hash should change when pure css chunk changes' , async ( ) => {
59
+ const buildProject = async ( cssColor : string ) => {
60
+ return ( await build ( {
61
+ root : resolve ( __dirname , 'packages/build-project' ) ,
62
+ logLevel : 'silent' ,
63
+ build : {
64
+ write : false ,
65
+ } ,
66
+ plugins : [
67
+ {
68
+ name : 'test' ,
69
+ resolveId ( id ) {
70
+ if (
71
+ id === 'entry.js' ||
72
+ id === 'foo.js' ||
73
+ id === 'bar.js' ||
74
+ id === 'baz.js' ||
75
+ id === 'foo.css' ||
76
+ id === 'bar.css' ||
77
+ id === 'baz.css'
78
+ ) {
79
+ return '\0' + id
80
+ }
81
+ } ,
82
+ load ( id ) {
83
+ if ( id === '\0entry.js' ) {
84
+ return `
85
+ window.addEventListener('click', () => { import('foo.js') });
86
+ window.addEventListener('click', () => { import('bar.js') });`
87
+ }
88
+ if ( id === '\0foo.js' ) return `import 'foo.css'; import 'baz.js'`
89
+ if ( id === '\0bar.js' ) return `import 'bar.css'; import 'baz.js'`
90
+ if ( id === '\0baz.js' ) return `import 'baz.css'`
91
+ if ( id === '\0foo.css' ) return `.foo { color: red }`
92
+ if ( id === '\0bar.css' ) return `.foo { color: green }`
93
+ if ( id === '\0baz.css' ) return `.foo { color: ${ cssColor } }`
94
+ } ,
95
+ } ,
96
+ ] ,
97
+ } ) ) as RollupOutput
98
+ }
99
+ const result = await Promise . all ( [
100
+ buildProject ( 'yellow' ) ,
101
+ buildProject ( 'blue' ) ,
102
+ ] )
103
+ assertOutputHashContentChange ( result [ 0 ] , result [ 1 ] )
104
+ } )
105
+ } )
106
+
14
107
const baseLibOptions : LibraryOptions = {
15
108
fileName : 'my-lib' ,
16
109
entry : 'mylib.js' ,
@@ -439,3 +532,26 @@ describe('resolveBuildOutputs', () => {
439
532
)
440
533
} )
441
534
} )
535
+
536
+ /**
537
+ * for each chunks in output1, if there's a chunk in output2 with the same fileName,
538
+ * ensure that the chunk code is the same. if not, the chunk hash should have changed.
539
+ */
540
+ function assertOutputHashContentChange (
541
+ output1 : RollupOutput ,
542
+ output2 : RollupOutput ,
543
+ ) {
544
+ for ( const chunk of output1 . output ) {
545
+ if ( chunk . type === 'chunk' ) {
546
+ const chunk2 = output2 . output . find (
547
+ ( c ) => c . type === 'chunk' && c . fileName === chunk . fileName ,
548
+ ) as OutputChunk | undefined
549
+ if ( chunk2 ) {
550
+ expect (
551
+ chunk . code ,
552
+ `the ${ chunk . fileName } chunk has the same hash but different contents between builds` ,
553
+ ) . toEqual ( chunk2 . code )
554
+ }
555
+ }
556
+ }
557
+ }
0 commit comments