未验证 提交 08ab3ac6 编写于 作者: T Tim Neutkens 提交者: GitHub

Fix mini-css-plugin webpack 5 deprecation warnings (#16390)

Solves the warnings coming from mini-css-plugin in webpack 5.

Fixes #15947
上级 3e81809d
......@@ -12,6 +12,7 @@ const {
util: { createHash },
} = webpack
const isWebpack5 = parseInt(webpack.version) === 5
const MODULE_TYPE = 'css/mini-extract'
const pluginName = 'mini-css-extract-plugin'
......@@ -22,6 +23,14 @@ const REGEXP_NAME = /\[name\]/i
const REGEXP_PLACEHOLDERS = /\[(name|id|chunkhash)\]/g
const DEFAULT_FILENAME = '[name].css'
function getModulesIterable(compilation, chunk) {
if (isWebpack5) {
return compilation.chunkGraph.getChunkModulesIterable(chunk)
}
return chunk.modulesIterable
}
class CssDependencyTemplate {
apply() {}
}
......@@ -68,94 +77,103 @@ class MiniCssExtractPlugin {
new CssDependencyTemplate()
)
compilation.mainTemplate.hooks.renderManifest.tap(
pluginName,
(result, { chunk }) => {
const renderedModules = Array.from(chunk.modulesIterable).filter(
(module) => module.type === MODULE_TYPE
)
const renderManifestFn = (result, { chunk }) => {
const renderedModules = Array.from(
getModulesIterable(compilation, chunk)
).filter((module) => module.type === MODULE_TYPE)
if (renderedModules.length > 0) {
result.push({
render: () =>
this.renderContentAsset(
compilation,
chunk,
renderedModules,
compilation.runtimeTemplate.requestShortener
),
filenameTemplate: ({ chunk: chunkData }) =>
this.options.moduleFilename(chunkData),
pathOptions: {
if (renderedModules.length > 0) {
result.push({
render: () =>
this.renderContentAsset(
compilation,
chunk,
contentHashType: MODULE_TYPE,
},
identifier: `${pluginName}.${chunk.id}`,
hash: chunk.contentHash[MODULE_TYPE],
})
}
renderedModules,
compilation.runtimeTemplate.requestShortener
),
filenameTemplate: ({ chunk: chunkData }) =>
this.options.moduleFilename(chunkData),
pathOptions: {
chunk,
contentHashType: MODULE_TYPE,
},
identifier: `${pluginName}.${chunk.id}`,
hash: chunk.contentHash[MODULE_TYPE],
})
}
)
compilation.chunkTemplate.hooks.renderManifest.tap(
pluginName,
(result, { chunk }) => {
const renderedModules = Array.from(chunk.modulesIterable).filter(
(module) => module.type === MODULE_TYPE
)
}
if (renderedModules.length > 0) {
result.push({
render: () =>
this.renderContentAsset(
compilation,
chunk,
renderedModules,
compilation.runtimeTemplate.requestShortener
),
filenameTemplate: this.options.chunkFilename,
pathOptions: {
chunk,
contentHashType: MODULE_TYPE,
},
identifier: `${pluginName}.${chunk.id}`,
hash: chunk.contentHash[MODULE_TYPE],
})
}
}
)
if (isWebpack5) {
compilation.hooks.renderManifest.tap(pluginName, renderManifestFn)
} else {
// In webpack 5 the 2 separate hooks are now one hook: `compilation.hooks.renderManifest`
// So we no longer have to double-apply the same function
compilation.mainTemplate.hooks.renderManifest.tap(
pluginName,
renderManifestFn
)
compilation.chunkTemplate.hooks.renderManifest.tap(
pluginName,
renderManifestFn
)
}
compilation.mainTemplate.hooks.hashForChunk.tap(
pluginName,
(hash, chunk) => {
const { chunkFilename } = this.options
const handleHashForChunk = (hash, chunk) => {
const { chunkFilename } = this.options
if (REGEXP_CHUNKHASH.test(chunkFilename)) {
hash.update(JSON.stringify(chunk.getChunkMaps(true).hash))
}
if (REGEXP_CHUNKHASH.test(chunkFilename)) {
hash.update(JSON.stringify(chunk.getChunkMaps(true).hash))
}
if (REGEXP_CONTENTHASH.test(chunkFilename)) {
hash.update(
JSON.stringify(
chunk.getChunkMaps(true).contentHash[MODULE_TYPE] || {}
)
if (REGEXP_CONTENTHASH.test(chunkFilename)) {
hash.update(
JSON.stringify(
chunk.getChunkMaps(true).contentHash[MODULE_TYPE] || {}
)
}
)
}
if (REGEXP_NAME.test(chunkFilename)) {
hash.update(JSON.stringify(chunk.getChunkMaps(true).name))
}
if (REGEXP_NAME.test(chunkFilename)) {
hash.update(JSON.stringify(chunk.getChunkMaps(true).name))
}
)
}
if (isWebpack5) {
const JSModulesHooks = webpack.javascript.JavascriptModulesPlugin.getCompilationHooks(
compilation
)
JSModulesHooks.chunkHash.tap(pluginName, (chunk, hash) => {
if (!chunk.hasRuntime()) return
return handleHashForChunk(hash, chunk)
})
} else {
compilation.mainTemplate.hooks.hashForChunk.tap(
pluginName,
handleHashForChunk
)
}
compilation.hooks.contentHash.tap(pluginName, (chunk) => {
const { outputOptions } = compilation
const { hashFunction, hashDigest, hashDigestLength } = outputOptions
const hash = createHash(hashFunction)
for (const m of chunk.modulesIterable) {
if (m.type === MODULE_TYPE) {
m.updateHash(hash)
const modules = getModulesIterable(compilation, chunk)
if (modules) {
if (isWebpack5) {
const xor = new (require('webpack/lib/util/StringXor'))()
for (const m of modules) {
if (m.type === MODULE_TYPE) {
xor.add(compilation.chunkGraph.getModuleHash(m, chunk.runtime))
}
}
xor.updateHash(hash)
} else {
for (const m of modules) {
if (m.type === MODULE_TYPE) {
m.updateHash(hash)
}
}
}
}
......@@ -169,7 +187,7 @@ class MiniCssExtractPlugin {
const { mainTemplate } = compilation
mainTemplate.hooks.localVars.tap(pluginName, (source, chunk) => {
const chunkMap = this.getCssChunkObject(chunk)
const chunkMap = this.getCssChunkObject(compilation, chunk)
if (Object.keys(chunkMap).length > 0) {
return Template.asString([
......@@ -190,7 +208,7 @@ class MiniCssExtractPlugin {
mainTemplate.hooks.requireEnsure.tap(
pluginName,
(source, chunk, hash) => {
const chunkMap = this.getCssChunkObject(chunk)
const chunkMap = this.getCssChunkObject(compilation, chunk)
if (Object.keys(chunkMap).length > 0) {
const chunkMaps = chunk.getChunkMaps()
......@@ -322,11 +340,11 @@ class MiniCssExtractPlugin {
})
}
getCssChunkObject(mainChunk) {
getCssChunkObject(compilation, mainChunk) {
const obj = {}
for (const chunk of mainChunk.getAllAsyncChunks()) {
for (const module of chunk.modulesIterable) {
for (const module of getModulesIterable(compilation, chunk)) {
if (module.type === MODULE_TYPE) {
obj[chunk.id] = 1
break
......@@ -342,7 +360,9 @@ class MiniCssExtractPlugin {
const [chunkGroup] = chunk.groupsIterable
if (typeof chunkGroup.getModuleIndex2 === 'function') {
const getModulePostOrderIndex =
chunkGroup.getModulePostOrderIndex || chunkGroup.getModuleIndex2
if (typeof getModulePostOrderIndex === 'function') {
// Store dependencies for modules
const moduleDependencies = new Map(modules.map((m) => [m, new Set()]))
const moduleDependenciesReasons = new Map(
......@@ -357,7 +377,9 @@ class MiniCssExtractPlugin {
.map((m) => {
return {
module: m,
index: cg.getModuleIndex2(m),
index: isWebpack5
? cg.getModulePostOrderIndex(m)
: cg.getModuleIndex2(m),
}
})
// eslint-disable-next-line no-undefined
......
......@@ -6,6 +6,7 @@ import NodeTargetPlugin from 'webpack/lib/node/NodeTargetPlugin'
import CssDependency from './CssDependency'
const isWebpack5 = parseInt(webpack.version) === 5
const pluginName = 'mini-css-extract-plugin'
function evalModuleCode(loaderContext, code, filename) {
......@@ -18,9 +19,17 @@ function evalModuleCode(loaderContext, code, filename) {
return module.exports
}
function findModuleById(modules, id) {
for (const module of modules) {
if (module.id === id) {
function getModuleId(compilation, module) {
if (isWebpack5) {
return compilation.chunkGraph.getModuleId(module)
}
return module.id
}
function findModuleById(compilation, id) {
for (const module of compilation.modules) {
if (getModuleId(compilation, module) === id) {
return module
}
}
......@@ -47,6 +56,10 @@ export function pitch(request) {
const outputOptions = {
filename: childFilename,
publicPath,
library: {
type: 'commonjs2',
name: null,
},
}
const childCompiler = this._compilation.createChildCompiler(
`${pluginName} ${request}`,
......@@ -54,53 +67,80 @@ export function pitch(request) {
)
new webpack.node.NodeTemplatePlugin(outputOptions).apply(childCompiler)
new webpack.LibraryTemplatePlugin(null, 'commonjs2').apply(childCompiler)
if (isWebpack5) {
new webpack.library.EnableLibraryPlugin(outputOptions.library.type).apply(
childCompiler
)
} else {
new webpack.LibraryTemplatePlugin(null, 'commonjs2').apply(childCompiler)
}
new NodeTargetPlugin().apply(childCompiler)
new webpack.SingleEntryPlugin(this.context, `!!${request}`, pluginName).apply(
childCompiler
)
new (isWebpack5 ? webpack.EntryPlugin : webpack.SingleEntryPlugin)(
this.context,
`!!${request}`,
pluginName
).apply(childCompiler)
new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 }).apply(
childCompiler
)
let source
childCompiler.hooks.thisCompilation.tap(
`${pluginName} loader`,
(compilation) => {
compilation.hooks.normalModuleLoader.tap(
`${pluginName} loader`,
(loaderContext, module) => {
const hook = isWebpack5
? webpack.NormalModule.getCompilationHooks(compilation).loader
: compilation.hooks.normalModuleLoader
hook.tap(`${pluginName} loader`, (loaderContext, module) => {
// eslint-disable-next-line no-param-reassign
loaderContext.emitFile = this.emitFile
if (module.request === request) {
// eslint-disable-next-line no-param-reassign
loaderContext.emitFile = this.emitFile
if (module.request === request) {
// eslint-disable-next-line no-param-reassign
module.loaders = loaders.map((loader) => {
return {
loader: loader.path,
options: loader.options,
ident: loader.ident,
}
})
}
module.loaders = loaders.map((loader) => {
return {
loader: loader.path,
options: loader.options,
ident: loader.ident,
}
})
}
)
})
if (isWebpack5) {
compilation.hooks.processAssets.tap(
{
name: pluginName,
// @ts-ignore TODO: Remove ignore when webpack 5 is stable
stage: webpack.Compilation.PROCESS_ASSETS_STAGE_ADDITIONAL,
},
(assets) => {
source = assets[childFilename] && assets[childFilename].source()
// Remove all chunk assets
Object.keys(assets).forEach((file) => delete assets[file])
}
)
}
}
)
let source
childCompiler.hooks.afterCompile.tap(pluginName, (compilation) => {
source =
compilation.assets[childFilename] &&
compilation.assets[childFilename].source()
// Remove all chunk assets
compilation.chunks.forEach((chunk) => {
chunk.files.forEach((file) => {
delete compilation.assets[file] // eslint-disable-line no-param-reassign
// webpack 5 case is covered in hooks.thisCompilation above
if (!isWebpack5) {
childCompiler.hooks.afterCompile.tap(pluginName, (compilation) => {
source =
compilation.assets[childFilename] &&
compilation.assets[childFilename].source()
// Remove all chunk assets
compilation.chunks.forEach((chunk) => {
chunk.files.forEach((file) => {
delete compilation.assets[file] // eslint-disable-line no-param-reassign
})
})
})
})
}
const callback = this.async()
......@@ -158,7 +198,7 @@ export function pitch(request) {
dependencies = [[null, exports]]
} else {
dependencies = exports.map(([id, content, media, sourceMap]) => {
const module = findModuleById(compilation.modules, id)
const module = findModuleById(compilation, id)
return {
identifier: module.identifier(),
......
......@@ -30,6 +30,14 @@ type Source = { map: () => RawSourceMap } | null
const isWebpack5 = parseInt(webpack.version!) === 5
function getModuleId(compilation: any, module: any) {
if (isWebpack5) {
return compilation.chunkGraph.getModuleId(module)
}
return module.id
}
function getModuleSource(compilation: any, module: any): any {
if (isWebpack5) {
return (
......@@ -200,7 +208,7 @@ function getOverlayMiddleware(options: OverlayMiddlewareOptions) {
}
const module = [...compilation.modules].find(
(searchModule) => searchModule.id === id
(searchModule) => getModuleId(compilation, searchModule) === id
)
return getModuleSource(compilation, module)
} catch (err) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册