Skip to content
This repository was archived by the owner on Jun 8, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# Inline Chunk Manifest HTML Webpack Plugin
Extension plugin for `html-webpack-plugin` to inline webpack chunk manifest. Default inlines in head tag.
Standing on shoulders of giants, by using [chunk-manifest-webpack-plugin](https://github.com/soundcloud/chunk-manifest-webpack-plugin) internally to extract chunks from manifest.
Extension plugin for [html-webpack-plugin](https://github.com/jantimon/html-webpack-plugin) to inline webpack's chunk manifest. Defaults to inline in `<head>` tag.

[![Build Status](https://travis-ci.org/jouni-kantola/inline-chunk-manifest-html-webpack-plugin.svg?branch=master)](https://travis-ci.org/jouni-kantola/inline-chunk-manifest-html-webpack-plugin)

Expand Down
21 changes: 12 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "inline-chunk-manifest-html-webpack-plugin",
"version": "1.1.1",
"version": "2.0.0",
"description": "Extension plugin for html-webpack-plugin to inline webpack chunk manifest. Default inlines in head tag.",
"main": "./src/index.js",
"repository": {
Expand All @@ -21,16 +21,19 @@
"src"
],
"devDependencies": {
"ava": "^0.19.1",
"eslint": "^3.19.0",
"eslint-plugin-prettier": "^2.0.1",
"husky": "^0.13.3",
"lint-staged": "^3.4.0",
"nyc": "^10.2.0",
"prettier": "^1.1.0"
"ava": "^0.23.0",
"eslint": "^4.9.0",
"eslint-plugin-prettier": "^2.3.1",
"husky": "^0.14.3",
"lint-staged": "^4.3.0",
"nyc": "^11.2.1",
"prettier": "^1.7.4"
},
"dependencies": {
"chunk-manifest-webpack-plugin": "~1.0.0"
"webpack-sources": "^1.0.1"
},
"peerDependencies": {
"webpack": "^2.0.0 || ^3.0.0"
},
"scripts": {
"lint": "node_modules/.bin/eslint ./src",
Expand Down
95 changes: 95 additions & 0 deletions src/chunk-manifest-webpack-plugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/**
* This dependency plugin is a fork of:
* chunk-manifest-webpack-plugin (https://github.com/soundcloud/chunk-manifest-webpack-plugin)
*
* inline-chunk-manifest-html-webpack-plugin already enables inlining webpack's chunk manifest,
* and therefor has been extracted.
*/

"use strict";

const RawSource = require("webpack-sources").RawSource;

class ChunkManifestPlugin {
constructor(options) {
options = options || {};
this.manifestFilename = options.filename || "manifest.json";
this.manifestVariable = options.manifestVariable || "webpackManifest";
}

apply(compiler) {
const manifestFilename = this.manifestFilename;
const manifestVariable = this.manifestVariable;
let chunkFilename;

compiler.plugin("this-compilation", compilation => {
const mainTemplate = compilation.mainTemplate;
mainTemplate.plugin("require-ensure", function(
source,
chunk,
hash
/*, chunkIdVariableName */
) {
chunkFilename = this.outputOptions.chunkFilename;

if (chunkFilename) {
const chunkManifest = [chunk].reduce(function registerChunk(
manifest,
c
) {
if (c.id in manifest) return manifest;

if (c.hasRuntime()) {
manifest[c.id] = undefined;
} else {
const assetFilename = mainTemplate.applyPluginsWaterfall(
"asset-path",
chunkFilename,
{
hash,
chunk: c
}
);

manifest[c.id] = assetFilename;
}

return c.chunks.reduce(registerChunk, manifest);
},
{});

this.outputOptions.chunkFilename = "__CHUNK_MANIFEST__";

compilation.assets[manifestFilename] = new RawSource(
JSON.stringify(chunkManifest)
);
}

return source;
});
});

compiler.plugin("compilation", compilation => {
const mainTemplate = compilation.mainTemplate;
mainTemplate.plugin("require-ensure", function(
source,
chunk,
hash,
chunkIdVariableName
) {
if (chunkFilename) {
this.outputOptions.chunkFilename = chunkFilename;
}

const updatedSource = source.replace(
/"__CHUNK_MANIFEST__"/,
`window["${manifestVariable}"][${chunkIdVariableName}]`
);

return updatedSource;
});
});
}
}

module.exports = ChunkManifestPlugin;
14 changes: 7 additions & 7 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use strict";

const ChunkManifestPlugin = require("chunk-manifest-webpack-plugin");
const ChunkManifestPlugin = require("./chunk-manifest-webpack-plugin");

class InlineChunkManifestHtmlWebpackPlugin {
constructor(options) {
Expand All @@ -19,9 +19,8 @@ class InlineChunkManifestHtmlWebpackPlugin {
throw new TypeError("Extract manifest must be boolean");
}

this.extractManifest = options.extractManifest != null
? options.extractManifest
: true;
this.extractManifest =
options.extractManifest != null ? options.extractManifest : true;

const manifestPlugins = options.manifestPlugins;

Expand All @@ -38,9 +37,10 @@ class InlineChunkManifestHtmlWebpackPlugin {
})
];

this.plugins = manifestPlugins && manifestPlugins.length
? manifestPlugins
: defaultManifestPlugins;
this.plugins =
manifestPlugins && manifestPlugins.length
? manifestPlugins
: defaultManifestPlugins;
}

apply(compiler) {
Expand Down
81 changes: 81 additions & 0 deletions test/plugin-generate-chunk-manifest-asset-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import test from "ava";

import ChunkManifestPlugin from "../src/chunk-manifest-webpack-plugin";

const RawSource = require("webpack-sources").RawSource;

test.cb("generate asset for chunk manifest", t => {
const manifestFilename = "a.manifest";
const filenamePlaceholder = "[filename]";
const moduleSource = "";

const chunk = {
id: 1,
hasRuntime: () => true,
chunks: [
{
id: 2,
hasRuntime: () => false,
chunks: []
},
{
id: 2
}
]
};

let expected = {};
expected[manifestFilename] = new RawSource(
JSON.stringify({
"2": "2-a1234.js"
})
);

const compilationPluginEvent = (compilationEvent, ensure) => {
if (compilationEvent === "require-ensure") {
ensure.apply(
{
outputOptions: {
chunkFilename: filenamePlaceholder
}
},
[undefined, chunk, "a1234"]
);
}
};

const applyPluginsWaterfall = (event, filename, data) => {
if (event === "asset-path")
return filename.replace(
filenamePlaceholder,
`${data.chunk.id}-${data.hash}.js`
);

t.fail();
};

const pluginEvent = (event, compile) => {
if (event === "this-compilation") {
const compilation = {
mainTemplate: {
plugin: compilationPluginEvent,
applyPluginsWaterfall
},
assets: {}
};

compile(compilation);

t.deepEqual(compilation.assets, expected);
t.end();
}
};

const fakeCompiler = { plugin: pluginEvent };

const plugin = new ChunkManifestPlugin({
filename: manifestFilename
});

plugin.apply(fakeCompiler);
});
2 changes: 1 addition & 1 deletion test/plugin-init-test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import test from "ava";
import InlineChunkManifestHtmlWebpackPlugin from "../src/";
import ChunkManifestPlugin from "chunk-manifest-webpack-plugin";
import ChunkManifestPlugin from "../src/chunk-manifest-webpack-plugin";

test("has defaults", t => {
const expected = {
Expand Down
59 changes: 59 additions & 0 deletions test/plugin-reset-chunk-filename-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import test from "ava";

import ChunkManifestPlugin from "../src/chunk-manifest-webpack-plugin";

test.cb("generate asset for chunk manifest", t => {
const chunkFilename = "[filename]";

const chunk = {
id: 1,
hasRuntime: () => true,
chunks: []
};

const thisCompilationPluginEvent = (compilationEvent, ensure) => {
if (compilationEvent === "require-ensure") {
const outputOptions = { chunkFilename };

ensure.apply({ outputOptions }, [undefined, chunk]);

t.is(outputOptions.chunkFilename, "__CHUNK_MANIFEST__");
}
};

const compilationPluginEvent = (compilationEvent, ensure) => {
if (compilationEvent === "require-ensure") {
const outputOptions = { chunkFilename: "overwrite-this" };

ensure.apply({ outputOptions }, ["", chunk]);

t.is(outputOptions.chunkFilename, chunkFilename);
t.end();
}
};

const pluginEvent = (event, compile) => {
const compilation = {
mainTemplate: {
plugin: undefined
},
assets: {}
};

if (event === "this-compilation") {
compilation.mainTemplate.plugin = thisCompilationPluginEvent;
compile(compilation);
}

if (event === "compilation") {
compilation.mainTemplate.plugin = compilationPluginEvent;
compile(compilation);
}
};

const fakeCompiler = { plugin: pluginEvent };

const plugin = new ChunkManifestPlugin();

plugin.apply(fakeCompiler);
});
51 changes: 51 additions & 0 deletions test/plugin-runtime-replacement-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import test from "ava";

import ChunkManifestPlugin from "../src/chunk-manifest-webpack-plugin";

test.cb("replace runtime's chunk manifest with lookup", t => {
const chunkIdVariableName = "a-chunk-id-variable";
const manifestVariable = "manifest-variable";
const placeholder = `"__CHUNK_MANIFEST__"`;

const runtimeSource = [
"runtime-source-start",
placeholder,
";",
"runtime-source-end"
];

let expected = [...runtimeSource];
expected[1] = `window["${manifestVariable}"][${chunkIdVariableName}]`;

const compilationPluginEvent = (compilationEvent, ensure) => {
if (compilationEvent === "require-ensure") {
const updatedSource = ensure(
runtimeSource.join(""),
undefined,
undefined,
chunkIdVariableName
);
t.is(updatedSource, expected.join(""));
t.end();
}
};

const pluginEvent = (event, compile) => {
if (event === "compilation") {
const compilation = {
mainTemplate: {
plugin: compilationPluginEvent
}
};
compile(compilation);
}
};

const fakeCompiler = { plugin: pluginEvent };

const plugin = new ChunkManifestPlugin({
manifestVariable
});

plugin.apply(fakeCompiler);
});
Loading