Skip to content

Commit 1c778c7

Browse files
author
wangzongxu
committed
test: miniCssExtractPluginBeforeLinkAppend
1 parent bc49802 commit 1c778c7

File tree

6 files changed

+324
-8
lines changed

6 files changed

+324
-8
lines changed

package-lock.json

+2-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"loader-utils": "^1.1.0",
4747
"normalize-url": "1.9.1",
4848
"schema-utils": "^1.0.0",
49+
"tapable": "^1.1.3",
4950
"webpack-sources": "^1.1.0"
5051
},
5152
"devDependencies": {

src/index.js

+10-5
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,7 @@ const {
1313
Template,
1414
util: { createHash },
1515
} = webpack;
16-
const {
17-
SyncWaterfallHook,
18-
} = require("tapable");
16+
const { SyncWaterfallHook } = require('tapable');
1917

2018
const MODULE_TYPE = 'css/mini-extract';
2119

@@ -132,7 +130,10 @@ class MiniCssExtractPlugin {
132130

133131
apply(compiler) {
134132
compiler.hooks.thisCompilation.tap(pluginName, (compilation) => {
135-
compilation.hooks.miniCssExtractPluginBeforeLinkAppend = new SyncWaterfallHook(['source', 'chunk', 'hash'])
133+
// eslint-disable-next-line no-param-reassign
134+
compilation.hooks.miniCssExtractPluginBeforeLinkAppend = new SyncWaterfallHook(
135+
['source', 'chunk', 'hash']
136+
);
136137

137138
compilation.dependencyFactories.set(
138139
CssDependency,
@@ -382,7 +383,11 @@ class MiniCssExtractPlugin {
382383
])
383384
: '',
384385
'var head = document.getElementsByTagName("head")[0];',
385-
compilation.hooks.miniCssExtractPluginBeforeLinkAppend.call('', chunk, hash),
386+
compilation.hooks.miniCssExtractPluginBeforeLinkAppend.call(
387+
source,
388+
chunk,
389+
hash
390+
),
386391
'head.appendChild(linkTag);',
387392
]),
388393
'}).then(function() {',

test/BeforeLinkAppendHook.test.js

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import MiniCssExtractPlugin from '../src';
2+
3+
import { getCompiler, compile } from './helpers';
4+
5+
it('It should be able to inject successfully', async (done) => {
6+
class RewriteErrorHandler {
7+
// eslint-disable-next-line class-methods-use-this
8+
apply(compiler) {
9+
compiler.hooks.thisCompilation.tap(
10+
'RewriteErrorHandler',
11+
(compilation) => {
12+
compilation.hooks.miniCssExtractPluginBeforeLinkAppend.tap(
13+
'RewriteErrorHandler',
14+
(source, chunk, hash) => {
15+
expect(source).toBeDefined();
16+
expect(chunk).toBeDefined();
17+
expect(hash).toBeDefined();
18+
return 'head.onerror = console.error;';
19+
}
20+
);
21+
}
22+
);
23+
}
24+
}
25+
26+
const compiler = getCompiler(
27+
'./esmAsync.js',
28+
{ esModule: true },
29+
{
30+
mode: 'production',
31+
optimization: { minimize: false },
32+
plugins: [
33+
new MiniCssExtractPlugin({
34+
filename: '[name].css',
35+
chunkFilename: '[id].css',
36+
}),
37+
new RewriteErrorHandler(),
38+
],
39+
}
40+
);
41+
42+
const stats = await compile(compiler);
43+
const content = stats.compilation.assets['main.bundle.js'].source();
44+
45+
expect(stats.hasErrors()).toBe(false);
46+
expect(content).toMatchSnapshot();
47+
48+
done();
49+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`It should be able to inject successfully 1`] = `
4+
"/******/ (function(modules) { // webpackBootstrap
5+
/******/ // install a JSONP callback for chunk loading
6+
/******/ function webpackJsonpCallback(data) {
7+
/******/ var chunkIds = data[0];
8+
/******/ var moreModules = data[1];
9+
/******/
10+
/******/
11+
/******/ // add \\"moreModules\\" to the modules object,
12+
/******/ // then flag all \\"chunkIds\\" as loaded and fire callback
13+
/******/ var moduleId, chunkId, i = 0, resolves = [];
14+
/******/ for(;i < chunkIds.length; i++) {
15+
/******/ chunkId = chunkIds[i];
16+
/******/ if(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {
17+
/******/ resolves.push(installedChunks[chunkId][0]);
18+
/******/ }
19+
/******/ installedChunks[chunkId] = 0;
20+
/******/ }
21+
/******/ for(moduleId in moreModules) {
22+
/******/ if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {
23+
/******/ modules[moduleId] = moreModules[moduleId];
24+
/******/ }
25+
/******/ }
26+
/******/ if(parentJsonpFunction) parentJsonpFunction(data);
27+
/******/
28+
/******/ while(resolves.length) {
29+
/******/ resolves.shift()();
30+
/******/ }
31+
/******/
32+
/******/ };
33+
/******/
34+
/******/
35+
/******/ // The module cache
36+
/******/ var installedModules = {};
37+
/******/
38+
/******/ // object to store loaded CSS chunks
39+
/******/ var installedCssChunks = {
40+
/******/ 0: 0
41+
/******/ }
42+
/******/
43+
/******/ // object to store loaded and loading chunks
44+
/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched
45+
/******/ // Promise = chunk loading, 0 = chunk loaded
46+
/******/ var installedChunks = {
47+
/******/ 0: 0
48+
/******/ };
49+
/******/
50+
/******/
51+
/******/
52+
/******/ // script path function
53+
/******/ function jsonpScriptSrc(chunkId) {
54+
/******/ return __webpack_require__.p + \\"\\" + ({}[chunkId]||chunkId) + \\".chunk.js\\"
55+
/******/ }
56+
/******/
57+
/******/ // The require function
58+
/******/ function __webpack_require__(moduleId) {
59+
/******/
60+
/******/ // Check if module is in cache
61+
/******/ if(installedModules[moduleId]) {
62+
/******/ return installedModules[moduleId].exports;
63+
/******/ }
64+
/******/ // Create a new module (and put it into the cache)
65+
/******/ var module = installedModules[moduleId] = {
66+
/******/ i: moduleId,
67+
/******/ l: false,
68+
/******/ exports: {}
69+
/******/ };
70+
/******/
71+
/******/ // Execute the module function
72+
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
73+
/******/
74+
/******/ // Flag the module as loaded
75+
/******/ module.l = true;
76+
/******/
77+
/******/ // Return the exports of the module
78+
/******/ return module.exports;
79+
/******/ }
80+
/******/
81+
/******/ // This file contains only the entry chunk.
82+
/******/ // The chunk loading function for additional chunks
83+
/******/ __webpack_require__.e = function requireEnsure(chunkId) {
84+
/******/ var promises = [];
85+
/******/
86+
/******/
87+
/******/ // mini-css-extract-plugin CSS loading
88+
/******/ var cssChunks = {\\"1\\":1};
89+
/******/ if(installedCssChunks[chunkId]) promises.push(installedCssChunks[chunkId]);
90+
/******/ else if(installedCssChunks[chunkId] !== 0 && cssChunks[chunkId]) {
91+
/******/ promises.push(installedCssChunks[chunkId] = new Promise(function(resolve, reject) {
92+
/******/ var href = \\"\\" + chunkId + \\".css\\";
93+
/******/ var fullhref = __webpack_require__.p + href;
94+
/******/ var existingLinkTags = document.getElementsByTagName(\\"link\\");
95+
/******/ for(var i = 0; i < existingLinkTags.length; i++) {
96+
/******/ var tag = existingLinkTags[i];
97+
/******/ var dataHref = tag.getAttribute(\\"data-href\\") || tag.getAttribute(\\"href\\");
98+
/******/ if(tag.rel === \\"stylesheet\\" && (dataHref === href || dataHref === fullhref)) return resolve();
99+
/******/ }
100+
/******/ var existingStyleTags = document.getElementsByTagName(\\"style\\");
101+
/******/ for(var i = 0; i < existingStyleTags.length; i++) {
102+
/******/ var tag = existingStyleTags[i];
103+
/******/ var dataHref = tag.getAttribute(\\"data-href\\");
104+
/******/ if(dataHref === href || dataHref === fullhref) return resolve();
105+
/******/ }
106+
/******/ var linkTag = document.createElement(\\"link\\");
107+
/******/ linkTag.rel = \\"stylesheet\\";
108+
/******/ linkTag.type = \\"text/css\\";
109+
/******/ linkTag.onload = resolve;
110+
/******/ linkTag.onerror = function(event) {
111+
/******/ var request = event && event.target && event.target.src || fullhref;
112+
/******/ var err = new Error(\\"Loading CSS chunk \\" + chunkId + \\" failed.\\\\n(\\" + request + \\")\\");
113+
/******/ err.code = \\"CSS_CHUNK_LOAD_FAILED\\";
114+
/******/ err.request = request;
115+
/******/ delete installedCssChunks[chunkId]
116+
/******/ linkTag.parentNode.removeChild(linkTag)
117+
/******/ reject(err);
118+
/******/ };
119+
/******/ linkTag.href = fullhref;
120+
/******/
121+
/******/ var head = document.getElementsByTagName(\\"head\\")[0];
122+
/******/ head.onerror = console.error;
123+
/******/ head.appendChild(linkTag);
124+
/******/ }).then(function() {
125+
/******/ installedCssChunks[chunkId] = 0;
126+
/******/ }));
127+
/******/ }
128+
/******/
129+
/******/ // JSONP chunk loading for javascript
130+
/******/
131+
/******/ var installedChunkData = installedChunks[chunkId];
132+
/******/ if(installedChunkData !== 0) { // 0 means \\"already installed\\".
133+
/******/
134+
/******/ // a Promise means \\"currently loading\\".
135+
/******/ if(installedChunkData) {
136+
/******/ promises.push(installedChunkData[2]);
137+
/******/ } else {
138+
/******/ // setup Promise in chunk cache
139+
/******/ var promise = new Promise(function(resolve, reject) {
140+
/******/ installedChunkData = installedChunks[chunkId] = [resolve, reject];
141+
/******/ });
142+
/******/ promises.push(installedChunkData[2] = promise);
143+
/******/
144+
/******/ // start chunk loading
145+
/******/ var script = document.createElement('script');
146+
/******/ var onScriptComplete;
147+
/******/
148+
/******/ script.charset = 'utf-8';
149+
/******/ script.timeout = 120;
150+
/******/ if (__webpack_require__.nc) {
151+
/******/ script.setAttribute(\\"nonce\\", __webpack_require__.nc);
152+
/******/ }
153+
/******/ script.src = jsonpScriptSrc(chunkId);
154+
/******/
155+
/******/ // create error before stack unwound to get useful stacktrace later
156+
/******/ var error = new Error();
157+
/******/ onScriptComplete = function (event) {
158+
/******/ // avoid mem leaks in IE.
159+
/******/ script.onerror = script.onload = null;
160+
/******/ clearTimeout(timeout);
161+
/******/ var chunk = installedChunks[chunkId];
162+
/******/ if(chunk !== 0) {
163+
/******/ if(chunk) {
164+
/******/ var errorType = event && (event.type === 'load' ? 'missing' : event.type);
165+
/******/ var realSrc = event && event.target && event.target.src;
166+
/******/ error.message = 'Loading chunk ' + chunkId + ' failed.\\\\n(' + errorType + ': ' + realSrc + ')';
167+
/******/ error.name = 'ChunkLoadError';
168+
/******/ error.type = errorType;
169+
/******/ error.request = realSrc;
170+
/******/ chunk[1](error);
171+
/******/ }
172+
/******/ installedChunks[chunkId] = undefined;
173+
/******/ }
174+
/******/ };
175+
/******/ var timeout = setTimeout(function(){
176+
/******/ onScriptComplete({ type: 'timeout', target: script });
177+
/******/ }, 120000);
178+
/******/ script.onerror = script.onload = onScriptComplete;
179+
/******/ document.head.appendChild(script);
180+
/******/ }
181+
/******/ }
182+
/******/ return Promise.all(promises);
183+
/******/ };
184+
/******/
185+
/******/ // expose the modules object (__webpack_modules__)
186+
/******/ __webpack_require__.m = modules;
187+
/******/
188+
/******/ // expose the module cache
189+
/******/ __webpack_require__.c = installedModules;
190+
/******/
191+
/******/ // define getter function for harmony exports
192+
/******/ __webpack_require__.d = function(exports, name, getter) {
193+
/******/ if(!__webpack_require__.o(exports, name)) {
194+
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
195+
/******/ }
196+
/******/ };
197+
/******/
198+
/******/ // define __esModule on exports
199+
/******/ __webpack_require__.r = function(exports) {
200+
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
201+
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
202+
/******/ }
203+
/******/ Object.defineProperty(exports, '__esModule', { value: true });
204+
/******/ };
205+
/******/
206+
/******/ // create a fake namespace object
207+
/******/ // mode & 1: value is a module id, require it
208+
/******/ // mode & 2: merge all properties of value into the ns
209+
/******/ // mode & 4: return value when already ns object
210+
/******/ // mode & 8|1: behave like require
211+
/******/ __webpack_require__.t = function(value, mode) {
212+
/******/ if(mode & 1) value = __webpack_require__(value);
213+
/******/ if(mode & 8) return value;
214+
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
215+
/******/ var ns = Object.create(null);
216+
/******/ __webpack_require__.r(ns);
217+
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
218+
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
219+
/******/ return ns;
220+
/******/ };
221+
/******/
222+
/******/ // getDefaultExport function for compatibility with non-harmony modules
223+
/******/ __webpack_require__.n = function(module) {
224+
/******/ var getter = module && module.__esModule ?
225+
/******/ function getDefault() { return module['default']; } :
226+
/******/ function getModuleExports() { return module; };
227+
/******/ __webpack_require__.d(getter, 'a', getter);
228+
/******/ return getter;
229+
/******/ };
230+
/******/
231+
/******/ // Object.prototype.hasOwnProperty.call
232+
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
233+
/******/
234+
/******/ // __webpack_public_path__
235+
/******/ __webpack_require__.p = \\"\\";
236+
/******/
237+
/******/ // on error function for async loading
238+
/******/ __webpack_require__.oe = function(err) { console.error(err); throw err; };
239+
/******/
240+
/******/ var jsonpArray = window[\\"webpackJsonp\\"] = window[\\"webpackJsonp\\"] || [];
241+
/******/ var oldJsonpFunction = jsonpArray.push.bind(jsonpArray);
242+
/******/ jsonpArray.push = webpackJsonpCallback;
243+
/******/ jsonpArray = jsonpArray.slice();
244+
/******/ for(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);
245+
/******/ var parentJsonpFunction = oldJsonpFunction;
246+
/******/
247+
/******/
248+
/******/ // Load entry module and return exports
249+
/******/ return __webpack_require__(__webpack_require__.s = 0);
250+
/******/ })
251+
/************************************************************************/
252+
/******/ ([
253+
/* 0 */
254+
/***/ (function(module, exports, __webpack_require__) {
255+
256+
__webpack_require__.e(/* import() */ 1).then(__webpack_require__.bind(null, 1));
257+
258+
259+
/***/ })
260+
/******/ ]);"
261+
`;

test/fixtures/esmAsync.js

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import("./simple.css");

0 commit comments

Comments
 (0)