11"use strict" ;
2+ /**
3+ * @plugin html-res-webpack-plugin
4+ * @author heyli
5+ * @reference : https://github.com/ampedandwired/html-webpack-plugin
6+ */
27
38// debug mode
49const isDebug = false ,
510 IS_TO_STR = true ;
611
712const fs = require ( 'fs' ) ,
813 _ = require ( 'lodash' ) ,
14+ vm = require ( 'vm' ) ,
915 path = require ( 'path' ) ,
16+ Promise = require ( 'bluebird' ) ,
1017 minify = require ( 'html-minifier' ) . minify ,
18+ childCompiler = require ( './libs/compiler' ) ,
1119 utils = require ( './libs/utils' ) ,
1220 errors = require ( './libs/errors' ) ,
1321 loaderUtils = require ( 'loader-utils' ) ;
@@ -23,6 +31,7 @@ function HtmlResWebpackPlugin(options) {
2331 favicon : options . favicon || false ,
2432 templateContent : options . templateContent || function ( tpl ) { return tpl } ,
2533 cssPublicPath : options . cssPublicPath || null ,
34+ entryLog : options . entryLog || false ,
2635 } , options ) ;
2736
2837 this . logChunkName = true ;
@@ -65,41 +74,63 @@ HtmlResWebpackPlugin.prototype.checkRequiredOptions = function(options) {
6574 */
6675HtmlResWebpackPlugin . prototype . apply = function ( compiler , callback ) {
6776
68- compiler . plugin ( "make" , function ( compilation , callback ) {
77+ // format: loader!fiename
78+ this . options . templateLoaderName = this . getFullTemplatePath ( this . options . template ) ;
79+
80+ var compilationPromise = null ;
81+
82+ compiler . plugin ( "make" , ( compilation , callback ) => {
6983 isDebug && console . log ( "==================make================" ) ;
84+
85+ compilationPromise = childCompiler . compileTemplate ( this . options . templateLoaderName , compiler . context , this . options . filename , compilation ) ;
86+
7087 callback ( ) ;
7188 } ) ;
7289
7390
7491 // right after emit, files will be generated
7592 compiler . plugin ( "emit" , ( compilation , callback ) => {
7693 isDebug && console . log ( "===================emit===============" ) ;
77- // return basename, ie, /xxx/xxx.html return xxx.html
78- this . options . htmlFileName = this . addFileToWebpackAsset ( compilation , this . options . template , utils . getBaseName ( this . options . template , this . options . filename ) , IS_TO_STR ) ;
79-
80- // inject favicon
81- if ( this . options . favicon ) {
82- this . options . faviconFileName = this . addFileToWebpackAsset ( compilation , this . options . template , utils . getBaseName ( this . options . favicon , null ) ) ;
83- }
8494
85- // webpack options
86- this . webpackOptions = compilation . options ;
87-
88- if ( this . options . mode === 'default' ) {
89- this . buildStats ( compilation ) ;
90- // start injecting resource into html
91- this . injectAssets ( compilation ) ;
92- }
93- else if ( this . options . mode === 'html' ) {
94- this . buildStatsHtmlMode ( compilation ) ;
95- // process
96- this . processAssets ( compilation ) ;
97- }
98-
99- // compress html content
100- this . options . htmlMinify && this . compressHtml ( compilation ) ;
101-
102- callback ( ) ;
95+ Promise . resolve ( )
96+ . then ( ( ) => {
97+ return compilationPromise ;
98+ } )
99+ . then ( ( compiledTemplate ) => {
100+ return this . evaluateCompilationResult ( compilation , compiledTemplate . content ) ;
101+ } ) .
102+ then ( ( compiledResult ) => {
103+
104+ // return basename, ie, /xxx/xxx.html return xxx.html
105+ this . options . htmlFileName = this . addFileToWebpackAsset ( compilation , this . options . template , utils . getBaseName ( this . options . template , this . options . filename ) , IS_TO_STR , compiledResult ) ;
106+
107+ // inject favicon
108+ if ( this . options . favicon ) {
109+ this . options . faviconFileName = this . addFileToWebpackAsset ( compilation , this . options . template , utils . getBaseName ( this . options . favicon , null ) ) ;
110+ }
111+
112+ // webpack options
113+ this . webpackOptions = compilation . options ;
114+
115+ if ( this . options . mode === 'default' ) {
116+ this . buildStats ( compilation ) ;
117+ // start injecting resource into html
118+ this . injectAssets ( compilation ) ;
119+ }
120+ else if ( this . options . mode === 'html' ) {
121+ this . buildStatsHtmlMode ( compilation ) ;
122+ // process
123+ this . processAssets ( compilation ) ;
124+ }
125+
126+ // compress html content
127+ this . options . htmlMinify && this . compressHtml ( compilation ) ;
128+
129+ callback ( ) ;
130+
131+ // console.log(compiledResult);
132+
133+ } ) ;
103134 } ) ;
104135
105136} ;
@@ -126,12 +157,52 @@ HtmlResWebpackPlugin.prototype.buildStatsHtmlMode = function(compilation) {
126157 }
127158
128159 this . logChunkName = false ;
129- console . log ( "=====html-res-webapck-plugin=====" ) ;
130- Object . keys ( this . stats . assets ) . map ( ( chunk , key ) => {
131- console . log ( "chunk" + ( key + 1 ) + ": " + chunk ) ;
160+ this . printChunkName ( this . stats . assets ) ;
161+
162+ } ;
163+
164+ HtmlResWebpackPlugin . prototype . printChunkName = function ( assets ) {
165+
166+ let assetsArray = Object . keys ( assets ) ;
167+
168+ if ( ! assetsArray . length || ! this . options . entryLog ) {
169+ return ;
170+ }
171+
172+ utils . alert ( '=====html-res-webapck-plugin=====' ) ;
173+ utils . alert ( 'assets used like:' ) ;
174+ utils . alert ( '<link rel="stylesheet" href="' + assetsArray [ 0 ] + '">' ) ;
175+ utils . alert ( '<script src="' + assetsArray [ 0 ] + '"></script>' ) ;
176+
177+ assetsArray . map ( ( chunk , key ) => {
178+ utils . info ( "chunk" + ( key + 1 ) + ": " + chunk ) ;
132179 } ) ;
133180} ;
134181
182+ HtmlResWebpackPlugin . prototype . evaluateCompilationResult = function ( compilation , source ) {
183+ if ( ! source ) {
184+ return Promise . reject ( 'The child compilation didn\'t provide a result' ) ;
185+ }
186+
187+ // The LibraryTemplatePlugin stores the template result in a local variable.
188+ // To extract the result during the evaluation this part has to be removed.
189+ source = source . replace ( 'var HTML_RES_WEBPACK_PLUGIN_RESULT =' , '' ) ;
190+ var template = this . options . templateLoaderName . replace ( / ^ .+ ! / , '' ) . replace ( / \? .+ $ / , '' ) ;
191+ var vmContext = vm . createContext ( _ . extend ( { HTML_WEBPACK_PLUGIN : true , require : require } , global ) ) ;
192+ var vmScript = new vm . Script ( source , { filename : template } ) ;
193+ // console.log(vmScript);
194+ // Evaluate code and cast to string
195+ var newSource ;
196+ try {
197+ newSource = vmScript . runInContext ( vmContext ) ;
198+ } catch ( e ) {
199+ return Promise . reject ( e ) ;
200+ }
201+ return typeof newSource === 'string' || typeof newSource === 'function'
202+ ? Promise . resolve ( newSource )
203+ : Promise . reject ( 'The loader "' + this . options . templateLoaderName + '" didn\'t return html.' ) ;
204+ } ;
205+
135206/**
136207 * find resources related the html
137208 * @param {[type] } compilation [description]
@@ -383,13 +454,13 @@ HtmlResWebpackPlugin.prototype.inlineRes = function(compilation, chunk, file, fi
383454 * @param {[type] } template [description]
384455 * @param {Boolean } isToStr [description]
385456 */
386- HtmlResWebpackPlugin . prototype . addFileToWebpackAsset = function ( compilation , template , basename , isToStr ) {
457+ HtmlResWebpackPlugin . prototype . addFileToWebpackAsset = function ( compilation , template , basename , isToStr , source ) {
387458 var filename = path . resolve ( template ) ;
388459
389460 compilation . fileDependencies . push ( filename ) ;
390461 compilation . assets [ basename ] = {
391462 source : ( ) => {
392- let fileContent = ( isToStr ) ? fs . readFileSync ( filename ) . toString ( ) : fs . readFileSync ( filename ) ;
463+ let fileContent = ( isToStr ) ? source : fs . readFileSync ( filename ) ;
393464 return fileContent ;
394465 } ,
395466 size : ( ) => {
@@ -400,6 +471,23 @@ HtmlResWebpackPlugin.prototype.addFileToWebpackAsset = function(compilation, tem
400471 return basename ;
401472} ;
402473
474+ /**
475+ * Helper to return the absolute template path with a fallback loader
476+ */
477+ HtmlResWebpackPlugin . prototype . getFullTemplatePath = function ( template , context ) {
478+ // If the template doesn't use a loader use the lodash template loader
479+ if ( template . indexOf ( '!' ) === - 1 ) {
480+ template = require . resolve ( './libs/loader.js' ) + '!' + template ;
481+ }
482+ // Resolve template path
483+
484+ return template . replace (
485+ / ( [ ! ] ) ( [ ^ \/ \\ ] [ ^ ! \? ] + | [ ^ \/ \\ ! ? ] ) ( $ | \? .+ $ ) / ,
486+ function ( match , prefix , filepath , postfix ) {
487+ return prefix + path . resolve ( filepath ) + postfix ;
488+ } ) ;
489+ } ;
490+
403491/**
404492 * compress html files
405493 * @param {[type] } compilation [description]
0 commit comments