Skip to content

Commit

Permalink
feat: add beforeTagInsert hook
Browse files Browse the repository at this point in the history
  • Loading branch information
msidolphin committed Jan 29, 2024
1 parent 8480bce commit e7aac21
Show file tree
Hide file tree
Showing 20 changed files with 206 additions and 7 deletions.
3 changes: 2 additions & 1 deletion .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
"vspace",
"commitlint",
"unreload",
"cnfg"
"cnfg",
"tapable"
],

"ignorePaths": [
Expand Down
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1194,6 +1194,27 @@ If you'd like to extract the media queries from the extracted CSS (so mobile use
- [Media Query Plugin](https://github.com/SassNinja/media-query-plugin)
- [Media Query Splitting Plugin](https://github.com/mike-diamond/media-query-splitting-plugin)

## Hooks

The mini-css-extract-plugin provides hooks to extend it to your needs.

### beforeTagInsert

`SyncWaterfallHook`

Called before inject the insert code for link tag. Should return a string

```javascript
MiniCssExtractPlugin.getHooks(compiler).beforeTagInsert.tap(
"changeHref",
(source, varNames) =>
compiler.webpack.Template.asString([
source,
`${varNames.tag}.setAttribute("href", "https://github.com/webpack-contrib/mini-css-extract-plugin");`,
])
);
```

## Contributing

Please take a moment to read our contributing guidelines if you haven't yet done so.
Expand Down
3 changes: 1 addition & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@
"webpack": "^5.0.0"
},
"dependencies": {
"schema-utils": "^4.0.0"
"schema-utils": "^4.0.0",
"tapable": "^2.2.1"
},
"devDependencies": {
"@babel/cli": "^7.21.0",
Expand Down
46 changes: 46 additions & 0 deletions src/hooks.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/** @typedef {import("webpack").Compiler} WebpackCompiler */
/**
* @typedef {Object} VarNames
* @property {string} tag
* @property {string} chunkId
* @property {string} href
* @property {string} resolve
* @property {string} reject
*/
/**
* @typedef {Object} MiniCssExtractHooks
* @property {import("tapable").SyncWaterfallHook<[string, VarNames]>} beforeTagInsert
*/

const { SyncWaterfallHook } = require("tapable");

/**
* @type {WeakMap<WebpackCompiler, MiniCssExtractHooks>}}
*/
const miniCssExtractHooksMap = new WeakMap();

/**
* @param {WebpackCompiler} complier
*/
function getHooks(complier) {
let hooks = miniCssExtractHooksMap.get(complier);
// Setup the hooks only once
if (!hooks) {
hooks = createHooks();
miniCssExtractHooksMap.set(complier, hooks);
}
return hooks;
}

/**
* @returns {MiniCssExtractHooks}
*/
function createHooks() {
return {
beforeTagInsert: new SyncWaterfallHook(["source", "varNames"]),
};
}

module.exports = {
getHooks,
};
20 changes: 19 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const {
getUndoPath,
BASE_URI,
} = require("./utils");
const { getHooks } = require("./hooks");

/** @typedef {import("schema-utils/declarations/validate").Schema} Schema */
/** @typedef {import("webpack").Compiler} Compiler */
Expand Down Expand Up @@ -513,6 +514,14 @@ class MiniCssExtractPlugin {
return CssDependency;
}

/**
* Returns all hooks for the given compiler
* @param {Compiler} compiler
*/
static getHooks(compiler) {
return getHooks(compiler);
}

/**
* @param {PluginOptions} [options]
*/
Expand Down Expand Up @@ -843,7 +852,6 @@ class MiniCssExtractPlugin {
if (!withLoading && !withHmr) {
return "";
}

return Template.asString([
'if (typeof document === "undefined") return;',
`var createStylesheet = ${runtimeTemplate.basicFunction(
Expand Down Expand Up @@ -902,6 +910,16 @@ class MiniCssExtractPlugin {
"}",
])
: "",
MiniCssExtractPlugin.getHooks(compiler).beforeTagInsert.call(
"",
{
tag: "linkTag",
chunkId: "chunkId",
href: "fullhref",
resolve: "resolve",
reject: "reject",
}
) || "",
typeof this.runtimeOptions.insert !== "undefined"
? typeof this.runtimeOptions.insert === "function"
? `(${this.runtimeOptions.insert.toString()})(linkTag)`
Expand Down
27 changes: 27 additions & 0 deletions test/api.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import path from "path";

import webpack from "webpack";

import MiniCssExtractPlugin from "../src";

import { getCompiler } from "./helpers/index";

describe("API", () => {
it("should return the same CssModule when same webpack instance provided", () => {
expect(MiniCssExtractPlugin.getCssModule(webpack)).toEqual(
Expand All @@ -14,4 +18,27 @@ describe("API", () => {
MiniCssExtractPlugin.getCssDependency(webpack)
);
});

it("should return the same Hooks when same webpack instance provided", () => {
const compiler = getCompiler(
"insert.js",
{},
{
mode: "none",
output: {
publicPath: "",
path: path.resolve(__dirname, "../outputs"),
filename: "[name].bundle.js",
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css",
}),
],
}
);
expect(MiniCssExtractPlugin.getHooks(compiler)).toEqual(
MiniCssExtractPlugin.getHooks(compiler)
);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ __webpack_require__.r(__webpack_exports__);
/******/
/******/ /* webpack/runtime/getFullHash */
/******/ (() => {
/******/ __webpack_require__.h = () => ("7f0e5fa686a9bb728e64")
/******/ __webpack_require__.h = () => ("04f5273a6b9819ed9e63")
/******/ })();
/******/
/******/ /* webpack/runtime/global */
Expand Down Expand Up @@ -201,6 +201,7 @@ __webpack_require__.r(__webpack_exports__);
/******/ linkTag.onerror = linkTag.onload = onLinkComplete;
/******/ linkTag.href = fullhref;
/******/
/******/
/******/ if (oldTag) {
/******/ oldTag.parentNode.insertBefore(linkTag, oldTag.nextSibling);
/******/ } else {
Expand Down
3 changes: 2 additions & 1 deletion test/cases/chunkFilename-fullhash/expected/webpack-5/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ __webpack_require__.r(__webpack_exports__);
/******/
/******/ /* webpack/runtime/getFullHash */
/******/ (() => {
/******/ __webpack_require__.h = () => ("100253bb7576627988e6")
/******/ __webpack_require__.h = () => ("04f5273a6b9819ed9e63")
/******/ })();
/******/
/******/ /* webpack/runtime/global */
Expand Down Expand Up @@ -201,6 +201,7 @@ __webpack_require__.r(__webpack_exports__);
/******/ linkTag.onerror = linkTag.onload = onLinkComplete;
/******/ linkTag.href = fullhref;
/******/
/******/
/******/ if (oldTag) {
/******/ oldTag.parentNode.insertBefore(linkTag, oldTag.nextSibling);
/******/ } else {
Expand Down
1 change: 1 addition & 0 deletions test/cases/hmr/expected/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -964,6 +964,7 @@ __webpack_require__.r(__webpack_exports__);
/******/ linkTag.onerror = linkTag.onload = onLinkComplete;
/******/ linkTag.href = fullhref;
/******/
/******/
/******/ if (oldTag) {
/******/ oldTag.parentNode.insertBefore(linkTag, oldTag.nextSibling);
/******/ } else {
Expand Down
1 change: 1 addition & 0 deletions test/cases/insert-function/expected/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@
/******/ linkTag.onerror = linkTag.onload = onLinkComplete;
/******/ linkTag.href = fullhref;
/******/
/******/
/******/ (function (linkTag) {
/******/ const reference = document.querySelector(".hot-reload");
/******/ if (reference) {
Expand Down
1 change: 1 addition & 0 deletions test/cases/insert-string/expected/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@
/******/ linkTag.onerror = linkTag.onload = onLinkComplete;
/******/ linkTag.href = fullhref;
/******/
/******/
/******/ var target = document.querySelector("script[src='1.js']");
/******/ target.parentNode.insertBefore(linkTag, target.nextSibling);
/******/ return linkTag;
Expand Down
1 change: 1 addition & 0 deletions test/cases/insert-undefined/expected/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@
/******/ linkTag.onerror = linkTag.onload = onLinkComplete;
/******/ linkTag.href = fullhref;
/******/
/******/
/******/ if (oldTag) {
/******/ oldTag.parentNode.insertBefore(linkTag, oldTag.nextSibling);
/******/ } else {
Expand Down
60 changes: 60 additions & 0 deletions test/hooks.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/* eslint-env browser */
import path from "path";

import MiniCssExtractPlugin from "../src";

import { runInJsDom, compile, getCompiler } from "./helpers/index";

describe("hooks", () => {
it(`beforeTagInsert`, async () => {
const webpackCompiler = getCompiler(
"insert.js",
{},
{
mode: "none",
output: {
publicPath: "",
path: path.resolve(__dirname, "../outputs"),
filename: "[name].bundle.js",
},
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css",
}),
{
apply: (compiler) => {
MiniCssExtractPlugin.getHooks(compiler).beforeTagInsert.tap(
"sri",
(source, varNames) =>
compiler.webpack.Template.asString([
source,
`${varNames.tag}.setAttribute("integrity", "sriHashes[${varNames.chunkId}]");`,
])
);
},
},
{
apply: (compiler) => {
MiniCssExtractPlugin.getHooks(compiler).beforeTagInsert.tap(
"changeHref",
(source, varNames) =>
compiler.webpack.Template.asString([
source,
`${varNames.tag}.setAttribute("href", "https://github.com/webpack-contrib/mini-css-extract-plugin");`,
])
);
},
},
],
}
);
const stats = await compile(webpackCompiler);
runInJsDom("main.bundle.js", webpackCompiler, stats, (dom) => {
const [tag] = dom.window.document.head.getElementsByTagName("link");
expect(tag.getAttribute("integrity")).toBe("sriHashes[chunkId]");
expect(tag.getAttribute("href")).toBe(
"https://github.com/webpack-contrib/mini-css-extract-plugin"
);
});
});
});
15 changes: 15 additions & 0 deletions types/hooks.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export type WebpackCompiler = import("webpack").Compiler;
export type VarNames = {
tag: string;
chunkId: string;
href: string;
resolve: string;
reject: string;
};
export type MiniCssExtractHooks = {
beforeTagInsert: import("tapable").SyncWaterfallHook<[string, VarNames]>;
};
/**
* @param {WebpackCompiler} complier
*/
export function getHooks(complier: WebpackCompiler): MiniCssExtractHooks;
5 changes: 5 additions & 0 deletions types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ declare class MiniCssExtractPlugin {
static getCssDependency(
webpack: Compiler["webpack"]
): CssDependencyConstructor;
/**
* Returns all hooks for the given compiler
* @param {Compiler} compiler
*/
static getHooks(compiler: Compiler): import("./hooks").MiniCssExtractHooks;
/**
* @param {PluginOptions} [options]
*/
Expand Down

0 comments on commit e7aac21

Please sign in to comment.