Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: allow consumers to access CssModule #703

Merged
merged 13 commits into from Feb 25, 2021
55 changes: 36 additions & 19 deletions src/index.js
Expand Up @@ -3,7 +3,7 @@
import { validate } from 'schema-utils';

import schema from './plugin-options.json';
import { shared, MODULE_TYPE, compareModulesByIdentifier } from './utils';
import { MODULE_TYPE, compareModulesByIdentifier } from './utils';

const pluginName = 'mini-css-extract-plugin';

Expand All @@ -18,8 +18,23 @@ const CODE_GENERATION_RESULT = {
runtimeRequirements: new Set(),
};

/**
* @type WeakMap<webpack, CssModule>
*/
const cssModuleCache = new WeakMap();
/**
* @type WeakMap<webpack, CssDependency>
*/
const cssDependencyCache = new WeakMap();

class MiniCssExtractPlugin {
static getCssModule(webpack) {
/**
* Prevent creation of multiple CssModule classes to allow other integrations to get the current CssModule.
*/
if (cssModuleCache.has(webpack)) {
return cssModuleCache.get(webpack);
}
class CssModule extends webpack.Module {
constructor({
context,
Expand Down Expand Up @@ -133,7 +148,9 @@ class MiniCssExtractPlugin {
super.deserialize(context);
}
}


cssModuleCache.set(webpack, CssModule);

if (
webpack.util &&
webpack.util.serialization &&
Expand Down Expand Up @@ -181,6 +198,12 @@ class MiniCssExtractPlugin {
}

static getCssDependency(webpack) {
/**
* Prevent creation of multiple CssDependency classes to allow other integrations to get the current CssDependency.
*/
if (cssDependencyCache.has(webpack)) {
return cssDependencyCache.get(webpack);
}
// eslint-disable-next-line no-shadow
class CssDependency extends webpack.Dependency {
constructor(
Expand Down Expand Up @@ -231,6 +254,8 @@ class MiniCssExtractPlugin {
}
}

cssDependencyCache.set(webpack, CssDependency);

if (
webpack.util &&
webpack.util.serialization &&
Expand Down Expand Up @@ -356,16 +381,8 @@ class MiniCssExtractPlugin {
}
}

// initializeCssDependency
// eslint-disable-next-line no-shadow
const { CssModule, CssDependency } = shared(webpack, (webpack) => {
// eslint-disable-next-line no-shadow
const CssModule = MiniCssExtractPlugin.getCssModule(webpack);
// eslint-disable-next-line no-shadow
const CssDependency = MiniCssExtractPlugin.getCssDependency(webpack);

return { CssModule, CssDependency };
});
const CssModule = MiniCssExtractPlugin.getCssModule(webpack);
const CssDependency = MiniCssExtractPlugin.getCssDependency(webpack);

compiler.hooks.thisCompilation.tap(pluginName, (compilation) => {
class CssModuleFactory {
Expand Down Expand Up @@ -1093,7 +1110,7 @@ class MiniCssExtractPlugin {
return usedModules;
}

modules = [...modules];
const modulesList = [...modules];

const [chunkGroup] = chunk.groupsIterable;
const moduleIndexFunctionName =
Expand All @@ -1103,16 +1120,16 @@ class MiniCssExtractPlugin {

if (typeof chunkGroup[moduleIndexFunctionName] === 'function') {
// Store dependencies for modules
const moduleDependencies = new Map(modules.map((m) => [m, new Set()]));
const moduleDependencies = new Map(modulesList.map((m) => [m, new Set()]));
const moduleDependenciesReasons = new Map(
modules.map((m) => [m, new Map()])
modulesList.map((m) => [m, new Map()])
);

// Get ordered list of modules per chunk group
// This loop also gathers dependencies from the ordered lists
// Lists are in reverse order to allow to use Array.pop()
const modulesByChunkGroup = Array.from(chunk.groupsIterable, (cg) => {
const sortedModules = modules
const sortedModules = modulesList
.map((m) => {
return {
module: m,
Expand Down Expand Up @@ -1145,7 +1162,7 @@ class MiniCssExtractPlugin {

const unusedModulesFilter = (m) => !usedModules.has(m);

while (usedModules.size < modules.length) {
while (usedModules.size < modulesList.length) {
let success = false;
let bestMatch;
let bestMatchDeps;
Expand Down Expand Up @@ -1227,8 +1244,8 @@ class MiniCssExtractPlugin {
// (to avoid a breaking change)
// TODO remove this in next major version
// and increase minimum webpack version to 4.12.0
modules.sort((a, b) => a.index2 - b.index2);
usedModules = modules;
modulesList.sort((a, b) => a.index2 - b.index2);
usedModules = modulesList;
}

this._sortedModulesCache.set(chunk, usedModules);
Expand Down
8 changes: 4 additions & 4 deletions src/loader.js
Expand Up @@ -3,9 +3,11 @@ import path from 'path';
import loaderUtils from 'loader-utils';
import { validate } from 'schema-utils';

import { shared, findModuleById, evalModuleCode } from './utils';
import { findModuleById, evalModuleCode } from './utils';
import schema from './loader-options.json';

import MiniCssExtractPlugin from './index';

const pluginName = 'mini-css-extract-plugin';

function hotLoader(content, context) {
Expand Down Expand Up @@ -199,9 +201,7 @@ export function pitch(request) {
}

const count = identifierCountMap.get(dependency.identifier) || 0;
const { CssDependency } = shared(webpack, () => {
return {};
});
const { CssDependency } = MiniCssExtractPlugin.getCssDependency(webpack)

if (!CssDependency) {
throw new Error(
Expand Down
19 changes: 0 additions & 19 deletions src/utils.js
Expand Up @@ -49,26 +49,7 @@ function compareModulesByIdentifier(a, b) {
return compareIds(a.identifier(), b.identifier());
}

const initializeCache = new WeakMap();

function shared(webpack, initializer) {
const cacheEntry = initializeCache.get(webpack);

// eslint-disable-next-line no-undefined
if (cacheEntry !== undefined) {
return cacheEntry;
}

const constructors = initializer(webpack);
const result = { ...constructors };

initializeCache.set(webpack, result);

return result;
}

export {
shared,
MODULE_TYPE,
findModuleById,
evalModuleCode,
Expand Down
15 changes: 15 additions & 0 deletions test/api.test.js
@@ -0,0 +1,15 @@
import webpack from 'webpack';

import MiniCssExtractPlugin from '../src';

describe('API', () => {

it('should return the same CssModule when same webpack instance provided', () => {
expect(MiniCssExtractPlugin.getCssModule(webpack)).toEqual(MiniCssExtractPlugin.getCssModule(webpack));
});

it('should return the same CssDependency when same webpack instance provided', () => {
expect(MiniCssExtractPlugin.getCssDependency(webpack)).toEqual(MiniCssExtractPlugin.getCssDependency(webpack));
});

});