1
+ import * as fs from 'fs' ;
1
2
import * as path from 'path' ;
2
3
import color from 'kleur' ;
3
4
import relative from 'require-relative' ;
4
- import { InputOption , RollupError } from 'rollup' ;
5
+ import {
6
+ InputOption ,
7
+ PluginContext ,
8
+ TransformResult ,
9
+ NormalizedInputOptions ,
10
+ NormalizedOutputOptions ,
11
+ RollupError ,
12
+ OutputBundle ,
13
+ OutputChunk
14
+ } from 'rollup' ;
15
+ import { ChunkResolver } from './chunk' ;
16
+ import { chunk_content_from_modules , extract_sourcemap , emit_code_and_sourcemap } from './code' ;
5
17
import { CompileResult } from './interfaces' ;
6
18
import RollupResult from './RollupResult' ;
7
19
8
20
const stderr = console . error . bind ( console ) ;
9
21
10
22
let rollup : any ;
11
23
24
+ const get_entry_point_output_chunk = ( bundle : OutputBundle , entry_point ?: string ) => {
25
+ if ( entry_point === undefined ) {
26
+ throw new Error ( "Internal error: entry_point cannot be undefined" ) ;
27
+ }
28
+
29
+ let entry_point_output_chunk : OutputChunk ;
30
+ for ( const chunk of Object . values ( bundle ) ) {
31
+ if ( ( chunk as OutputChunk ) . facadeModuleId === entry_point ) {
32
+ entry_point_output_chunk = chunk as OutputChunk ;
33
+ }
34
+ }
35
+
36
+ if ( ! entry_point_output_chunk ) {
37
+ throw new Error ( `Internal error: No chunk for entry point: ${ entry_point } in: ${ Object . keys ( bundle ) } ` ) ;
38
+ }
39
+
40
+ if ( entry_point_output_chunk . type !== 'chunk' ) {
41
+ throw new Error ( `Internal error: Wrong type for entry point chunk: ${ entry_point } in: ${ Object . keys ( bundle ) } ` ) ;
42
+ }
43
+
44
+ return entry_point_output_chunk ;
45
+ } ;
46
+
12
47
export default class RollupCompiler {
13
48
_ : Promise < any > ;
14
49
_oninvalid : ( filename : string ) => void ;
@@ -18,6 +53,7 @@ export default class RollupCompiler {
18
53
errors : any [ ] ;
19
54
chunks : any [ ] ;
20
55
css_files : Array < { id : string ; code : string } > ;
56
+ dependencies : Record < string , string [ ] > ;
21
57
22
58
constructor ( config : any ) {
23
59
this . _ = this . get_config ( config ) ;
@@ -26,23 +62,113 @@ export default class RollupCompiler {
26
62
this . errors = [ ] ;
27
63
this . chunks = [ ] ;
28
64
this . css_files = [ ] ;
65
+ this . dependencies = { } ;
29
66
}
30
67
31
68
async get_config ( mod : any ) {
69
+ let entry_point : string | undefined ;
70
+
71
+ const that = this ;
72
+ const sourcemap = mod . output . sourcemap ;
73
+
32
74
// TODO this is hacky, and doesn't need to apply to all three compilers
33
75
( mod . plugins || ( mod . plugins = [ ] ) ) . push ( {
34
76
name : 'sapper-internal' ,
35
- options : ( opts : any ) => {
36
- this . input = opts . input ;
77
+ options ( opts : any ) {
78
+ that . input = opts . input ;
79
+ } ,
80
+ buildStart ( this : PluginContext , options : NormalizedInputOptions ) : void {
81
+ const input = options . input ;
82
+ const inputs : Array < { alias : string , file : string } > = [ ] ;
83
+
84
+ if ( typeof input === 'string' ) {
85
+ inputs . push ( { alias : 'main' , file : input } ) ;
86
+ } else if ( Array . isArray ( input ) ) {
87
+ inputs . push ( ...input . map ( file => ( { file, alias : file } ) ) ) ;
88
+ } else {
89
+ for ( const alias in input ) {
90
+ inputs . push ( { file : input [ alias ] , alias} ) ;
91
+ }
92
+ }
93
+ if ( ! entry_point ) {
94
+ entry_point = inputs [ 0 ] . file ;
95
+ }
37
96
} ,
38
- renderChunk : ( code : string , chunk : any ) => {
39
- this . chunks . push ( chunk ) ;
97
+ renderChunk ( code : string , chunk : any ) {
98
+ that . chunks . push ( chunk ) ;
40
99
} ,
41
- transform : ( code : string , id : string ) => {
100
+ transform ( code : string , id : string ) : TransformResult {
101
+ // TODO: see if we can remove after release of https://github.com/sveltejs/rollup-plugin-svelte/pull/72
42
102
if ( / \. c s s $ / . test ( id ) ) {
43
- this . css_files . push ( { id, code } ) ;
103
+ that . css_files . push ( { id, code } ) ;
44
104
return { code : '' , moduleSideEffects : 'no-treeshake' } ;
45
105
}
106
+ } ,
107
+ async generateBundle ( this : PluginContext , options : NormalizedOutputOptions , bundle : OutputBundle ) : Promise < void > {
108
+ const entry_point_output_chunk = get_entry_point_output_chunk ( bundle , entry_point ) ;
109
+
110
+ const chunk_resolver = new ChunkResolver < OutputChunk > ( {
111
+ id : chunk => chunk . fileName ,
112
+ resolve_id : chunk_file => {
113
+ const oc = bundle [ chunk_file ] ;
114
+ return oc && oc . type === 'chunk' ? oc : undefined ;
115
+ } ,
116
+ internals : chunk => ( {
117
+ id : chunk . fileName ,
118
+ facadeId : chunk . facadeModuleId ,
119
+ name : chunk . name ,
120
+ file_name : chunk . fileName ,
121
+ dep_names : chunk === entry_point_output_chunk ? [ ...chunk . imports ] : [ ...chunk . imports , ...chunk . dynamicImports ] ,
122
+ manifest : Object . keys ( chunk . modules ) ,
123
+ type : options . format === 'es' ? 'module' : 'script'
124
+ } ) ,
125
+ module_imports : js_module => {
126
+ const module_info = this . getModuleInfo ( js_module ) ;
127
+ return [
128
+ ...module_info . importedIds ,
129
+ ...module_info . dynamicallyImportedIds
130
+ ] . filter ( id => / \. c s s $ / . test ( id ) ) ;
131
+ } ,
132
+ chunks_from_modules : ( chunk , css_modules ) => {
133
+ const name = chunk . name + '.css' ;
134
+ const file_name = emit_code_and_sourcemap ( {
135
+ sourcemap,
136
+ output : chunk_content_from_modules (
137
+ css_modules ,
138
+ css_module => {
139
+ const f = that . css_files . find ( file => file . id === css_module ) ;
140
+ return f && extract_sourcemap ( f . code , css_module ) ;
141
+ }
142
+ ) ,
143
+ sourcemap_url_prefix : '' ,
144
+ output_file_name : name ,
145
+ emit : ( filename : string , source : string | Uint8Array ) => {
146
+ const moduleid = this . emitFile ( { name : filename , type : 'asset' , source } ) ;
147
+ const file = this . getFileName ( moduleid ) ;
148
+ return file ;
149
+ }
150
+ } ) ;
151
+
152
+ return [ {
153
+ id : file_name ,
154
+ facadeId : chunk . facadeModuleId ,
155
+ name,
156
+ file_name,
157
+ manifest : css_modules ,
158
+ dep_names : [ ]
159
+ } ] ;
160
+ }
161
+ } ) ;
162
+
163
+ const output_chunks = Object . values ( bundle ) . filter ( output => output . type === 'chunk' ) as OutputChunk [ ] ;
164
+ const chunks = await Promise . all ( output_chunks . map ( chunk => chunk_resolver . resolve_chunk ( chunk ) ) ) ;
165
+ const dependencies = { } ;
166
+ for ( const chunk of chunks ) {
167
+ if ( chunk . facadeId ) {
168
+ dependencies [ chunk . facadeId ] = Array . from ( chunk . transitive_deps ) . map ( dep => dep . file_name ) ;
169
+ }
170
+ }
171
+ that . dependencies = dependencies ;
46
172
}
47
173
} ) ;
48
174
0 commit comments