diff --git a/declarations/plugins/BannerPlugin.d.ts b/declarations/plugins/BannerPlugin.d.ts index 0a4511c37..53165456f 100644 --- a/declarations/plugins/BannerPlugin.d.ts +++ b/declarations/plugins/BannerPlugin.d.ts @@ -38,6 +38,10 @@ export interface BannerPluginOptions { * Exclude all modules matching any of these conditions. */ exclude?: Rules; + /** + * If true, banner will be placed at the end of the output. + */ + footer?: boolean; /** * Include all modules matching any of these conditions. */ diff --git a/lib/BannerPlugin.js b/lib/BannerPlugin.js index 3c10558ac..94243ad82 100644 --- a/lib/BannerPlugin.js +++ b/lib/BannerPlugin.js @@ -106,7 +106,9 @@ class BannerPlugin { compilation.updateAsset(file, old => { let cached = cache.get(old); if (!cached || cached.comment !== comment) { - const source = new ConcatSource(comment, "\n", old); + const source = options.footer + ? new ConcatSource(old, "\n", comment) + : new ConcatSource(comment, "\n", old); cache.set(old, { source, comment }); return source; } diff --git a/schemas/plugins/BannerPlugin.check.js b/schemas/plugins/BannerPlugin.check.js index a780b149b..aa7cd0e95 100644 --- a/schemas/plugins/BannerPlugin.check.js +++ b/schemas/plugins/BannerPlugin.check.js @@ -3,4 +3,4 @@ * DO NOT MODIFY BY HAND. * Run `yarn special-lint-fix` to update */ -"use strict";function n(t,{instancePath:l="",parentData:s,parentDataProperty:e,rootData:a=t}={}){let r=null,o=0;const u=o;let i=!1;const p=o;if(o===p)if(Array.isArray(t)){const n=t.length;for(let l=0;l { - const entry1File = path.join(__dirname, "js", "BannerPlugin", "entry1.js"); - const entry2File = path.join(__dirname, "js", "BannerPlugin", "entry2.js"); + const entry1File = path.join(pluginDir, "entry1.js"); + const entry2File = path.join(pluginDir, "entry2.js"); + const outputFile = path.join(outputDir, "entry1.js"); try { - fs.mkdirSync(path.join(__dirname, "js", "BannerPlugin"), { + fs.mkdirSync(path.join(pluginDir), { recursive: true }); } catch (e) { @@ -22,7 +26,7 @@ it("should cache assets", done => { entry2: entry2File }, output: { - path: path.join(__dirname, "js", "BannerPlugin", "output") + path: outputDir }, plugins: [new webpack.BannerPlugin("banner is a string")] }); @@ -30,6 +34,8 @@ it("should cache assets", done => { fs.writeFileSync(entry2File, "1", "utf-8"); compiler.run(err => { if (err) return done(err); + const footerFileResults = fs.readFileSync(outputFile, "utf8").split("\n"); + expect(footerFileResults[0]).toBe("/*! banner is a string */"); fs.writeFileSync(entry2File, "2", "utf-8"); compiler.run((err, stats) => { const { assets } = stats.toJson(); @@ -39,3 +45,37 @@ it("should cache assets", done => { }); }); }); + +it("can place banner as footer", done => { + const footerFile = path.join(pluginDir, "footerFile.js"); + const outputFile = path.join(outputDir, "footerFile.js"); + try { + fs.mkdirSync(path.join(pluginDir), { + recursive: true + }); + } catch (e) { + // empty + } + const compiler = webpack({ + mode: "development", + entry: { + footerFile: footerFile + }, + output: { + path: outputDir + }, + plugins: [ + new webpack.BannerPlugin({ + banner: "banner is a string", + footer: true + }) + ] + }); + fs.writeFileSync(footerFile, "footer", "utf-8"); + compiler.run(err => { + if (err) return done(err); + const footerFileResults = fs.readFileSync(outputFile, "utf8").split("\n"); + expect(footerFileResults.pop()).toBe("/*! banner is a string */"); + done(); + }); +}); diff --git a/types.d.ts b/types.d.ts index b977fed15..a250c3c47 100644 --- a/types.d.ts +++ b/types.d.ts @@ -430,6 +430,11 @@ declare interface BannerPluginOptions { */ exclude?: string | RegExp | Rule[]; + /** + * If true, banner will be placed at the end of the output. + */ + footer?: boolean; + /** * Include all modules matching any of these conditions. */