Skip to content

Commit

Permalink
feat: basic support for webpack 5
Browse files Browse the repository at this point in the history
  • Loading branch information
Austaras committed Oct 20, 2020
1 parent 51b3771 commit 484a2d7
Show file tree
Hide file tree
Showing 23 changed files with 170 additions and 350 deletions.
Binary file removed .yarn-offline-mirror/html-webpack-plugin-4.3.0.tgz
Binary file not shown.
Binary file not shown.
Binary file added .yarn-offline-mirror/lodash-4.17.20.tgz
Binary file not shown.
Binary file not shown.
Binary file removed .yarn-offline-mirror/util.promisify-1.0.0.tgz
Binary file not shown.
14 changes: 0 additions & 14 deletions examples/vue-cssextract/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,4 @@ module.exports = {
],
}],
},

node: {
// prevent webpack from injecting useless setImmediate polyfill because Vue
// source contains it (although only uses it if it's native).
setImmediate: false,
// prevent webpack from injecting mocks to Node native modules
// that does not make sense for the client
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
// eslint-disable-next-line camelcase
child_process: 'empty',
},
}
14 changes: 0 additions & 14 deletions examples/vue-dynamic-import/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,4 @@ module.exports = {
},
],
},

node: {
// prevent webpack from injecting useless setImmediate polyfill because Vue
// source contains it (although only uses it if it's native).
setImmediate: false,
// prevent webpack from injecting mocks to Node native modules
// that does not make sense for the client
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
// eslint-disable-next-line camelcase
child_process: 'empty',
},
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@
"hard-source-webpack-plugin": "^0.13.1",
"html-loader": "^1.1.0",
"html-webpack-include-assets-plugin": "^2.0.0",
"html-webpack-plugin": "^4.3.0",
"html-webpack-plugin": "^5.0.0-alpha.6",
"jasmine-core": "^3.6.0",
"jasmine-spec-reporter": "^5.0.2",
"mini-css-extract-plugin": "^0.9.0",
Expand Down
25 changes: 15 additions & 10 deletions src/babel-target.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import { BabelLoaderTransformOptions, BabelPresetOptions } from 'babel-loader'
import * as webpack from 'webpack'
import Chunk = webpack.Chunk
import ChunkGroup = webpack.ChunkGroup
import Entrypoint = webpack.Entrypoint
import Module = webpack.Module
import { Chunk, ChunkGroup, ChunkGraph, Entrypoint, Module } from 'webpack'

import { BabelLoaderCacheDirectoryOption } from './babel.multi.target.options'
import { BabelTargetOptions } from './babel.target.options'
Expand Down Expand Up @@ -51,7 +47,8 @@ const SIG = {
'hasEntryModule',
'addModule',
'removeModule',
'setModules',
// This is removed in webpack@5
// 'setModules',
'getNumberOfModules',
'addGroup',
'isInGroup',
Expand Down Expand Up @@ -137,7 +134,7 @@ export class BabelTarget implements BabelTargetInfo {
}

public static getTargetFromModule(module: Module): BabelTarget {
if (module.options && module.options.babelTarget) {
if (module.options?.babelTarget) {
return module.options.babelTarget
}

Expand All @@ -146,7 +143,7 @@ export class BabelTarget implements BabelTargetInfo {
}

for (const reason of module.reasons) {
if (reason.dependency && reason.dependency.babelTarget) {
if (reason.dependency?.babelTarget) {
return reason.dependency.babelTarget
}
if (reason.module) {
Expand All @@ -162,10 +159,17 @@ export class BabelTarget implements BabelTargetInfo {
}

public static getTargetFromEntrypoint(entrypoint: Entrypoint): BabelTarget {
if (!entrypoint.runtimeChunk.hasEntryModule()) {
console.log(entrypoint.name, entrypoint.getRuntimeChunk().hasEntryModule())
if (!entrypoint.getRuntimeChunk().hasEntryModule()) {
return undefined
}
return BabelTarget.getTargetFromModule(entrypoint.runtimeChunk.entryModule)
const arr = Array.from(
ChunkGraph.getChunkGraphForChunk(
entrypoint.getRuntimeChunk(),
'Chunk.entryModule',
'DEP_WEBPACK_CHUNK_ENTRY_MODULE',
).getChunkEntryModulesIterable(entrypoint.getRuntimeChunk()))
return BabelTarget.getTargetFromModule(arr[0])
}

// eslint-disable-next-line
Expand All @@ -174,6 +178,7 @@ export class BabelTarget implements BabelTargetInfo {
}

public static getTargetFromChunk(chunk: Chunk): BabelTarget {
console.log(!!chunk.entryModule)
if (chunk.entryModule) {
return BabelTarget.getTargetFromModule(chunk.entryModule)
}
Expand Down
16 changes: 8 additions & 8 deletions src/babel.multi.target.html.updater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,18 +90,18 @@ export class BabelMultiTargetHtmlUpdater implements Plugin {

// not sure if this is a problem since webpack will wait for dependencies to load, but sorting
// by auto/dependency will result in a cyclic dependency error for lazy-loaded routes
htmlWebpackPlugin.options.chunksSortMode = 'none' as any
htmlWebpackPlugin.userOptions.chunksSortMode = 'none' as any

if ((htmlWebpackPlugin.options.chunks as any) !== 'all' &&
htmlWebpackPlugin.options.chunks &&
htmlWebpackPlugin.options.chunks.length
if ((htmlWebpackPlugin.userOptions.chunks as any) !== 'all' &&
htmlWebpackPlugin.userOptions.chunks &&
htmlWebpackPlugin.userOptions.chunks.length
) {
htmlWebpackPlugin.options.chunks = this.mapChunkNames(htmlWebpackPlugin.options.chunks as string[])
htmlWebpackPlugin.userOptions.chunks = this.mapChunkNames(htmlWebpackPlugin.userOptions.chunks as string[])
}

if (htmlWebpackPlugin.options.excludeChunks &&
htmlWebpackPlugin.options.excludeChunks.length) {
htmlWebpackPlugin.options.excludeChunks = this.mapChunkNames(htmlWebpackPlugin.options.excludeChunks)
if (htmlWebpackPlugin.userOptions.excludeChunks &&
htmlWebpackPlugin.userOptions.excludeChunks.length) {
htmlWebpackPlugin.userOptions.excludeChunks = this.mapChunkNames(htmlWebpackPlugin.userOptions.excludeChunks)
}

compiler.hooks.compilation.tap(PLUGIN_NAME, (compilation: Compilation) => {
Expand Down
3 changes: 2 additions & 1 deletion src/babel.multi.target.plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ export class BabelMultiTargetPlugin implements Plugin {
// magic starts here!
new BabelTargetEntryOptionPlugin(this.targets).apply(compiler)
new TargetingPlugin(this.targets, this.options.exclude, this.options.doNotTarget, compiler.options.externals).apply(compiler)
new NormalizeCssChunksPlugin(this.targets).apply(compiler)
// TODO
// new NormalizeCssChunksPlugin(this.targets).apply(compiler)
new BabelMultiTargetHtmlUpdater(this.targets).apply(compiler)
if (this.options.safari10NoModuleFix) {
new SafariNoModuleFixPlugin(this.options.safari10NoModuleFix).apply(compiler)
Expand Down
38 changes: 32 additions & 6 deletions src/babel.target.entry.dependency.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,40 @@
import { BabelTarget } from './babel-target'
import { DEV_SERVER_CLIENT } from './constants'

import Dependency = require('webpack/lib/Dependency')
import ModuleDependency = require('webpack/lib/dependencies/ModuleDependency')

export interface EntryLoc {
interface EntryLoc {
name: string
index?: number
}

export interface BabelTargetEntryDependency extends Dependency {
babelTarget: BabelTarget
loc: EntryLoc
name: string
// TODO what's makeSerializable?
export class BabelTargetEntryDependency extends ModuleDependency {

public name: string
public loc: EntryLoc

public get type(): string {
return 'babel target entry'
}

public getResourceIdentifier(): string {
return `module${this.request}!${this.babelTarget.key}`
}

public get category(): string {
return 'esm'
}

constructor(public babelTarget: BabelTarget, request: string, public originalName: string, loc?: EntryLoc) {
super(`${request.startsWith(DEV_SERVER_CLIENT) ? request : babelTarget.getTargetedRequest(request)}`)

this.name = babelTarget.getTargetedAssetName(originalName)
if (!loc) {
loc = { name: `${this.request}:${babelTarget.key}` }
} else {
loc.name += `:${babelTarget.key}`
}
this.loc = loc
}
}
58 changes: 43 additions & 15 deletions src/babel.target.entry.option.plugin.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { Compiler, Plugin } from 'webpack'

import { BabelTarget } from './babel-target'
import { BabelTargetMultiEntryPlugin } from './babel.target.multi.entry.plugin'
import { BabelTargetSingleEntryPlugin } from './babel.target.single.entry.plugin'
import { BabelTargetEntryPlugin } from './babel.target.entry.plugin'

// takes over processing of webpack's entry options so that it generates one entry per entry and target
// basically the same as webpack's built-in EntryOptionPlugin, just using the babel targeting stuff instead
Expand All @@ -15,27 +14,56 @@ export class BabelTargetEntryOptionPlugin implements Plugin {
constructor(private targets: BabelTarget[]) {
}

private itemToPlugin(context: string, item: string | string[], name: string): Plugin {
if (Array.isArray(item)) {
return new BabelTargetMultiEntryPlugin(this.targets, context, name, item)
// private itemToPlugin(context: string, item: string | string[], name: string): Plugin {
// if (Array.isArray(item)) {
// return new BabelTargetMultiEntryPlugin(this.targets, context, name, item)
// }
// if (this.targets.find(target => !!(target.additionalModules && target.additionalModules.length))) {
// return new BabelTargetMultiEntryPlugin(this.targets, context, name, [item])
// }
// return new BabelTargetSingleEntryPlugin(this.targets, context, name, item)
// }

private static entryDescriptionToOptions(compiler: Compiler, name: string, desc: any): any {
const options = {
name,
filename: desc.filename,
runtime: desc.runtime,
dependOn: desc.dependOn,
chunkLoading: desc.chunkLoading,
wasmLoading: desc.wasmLoading,
library: desc.library,
}
// TODO what does those plugins do?
if (desc.chunkLoading) {
// const EnableChunkLoadingPlugin = require("./javascript/EnableChunkLoadingPlugin")
// EnableChunkLoadingPlugin.checkEnabled(compiler, desc.chunkLoading)
}
if (this.targets.find(target => !!(target.additionalModules && target.additionalModules.length))) {
return new BabelTargetMultiEntryPlugin(this.targets, context, name, [item])
if (desc.wasmLoading) {
// const EnableWasmLoadingPlugin = require("./wasm/EnableWasmLoadingPlugin")
// EnableWasmLoadingPlugin.checkEnabled(compiler, desc.wasmLoading)
}
return new BabelTargetSingleEntryPlugin(this.targets, context, name, item)
if (desc.library) {
// const EnableLibraryPlugin = require("./library/EnableLibraryPlugin")
// EnableLibraryPlugin.checkEnabled(compiler, desc.library.type)
}
return options
}

public apply(compiler: Compiler): void {
compiler.hooks.entryOption.tap('EntryOptionPlugin', (context: string, entry: any) => {
if (typeof entry === 'string' || Array.isArray(entry)) {
this.itemToPlugin(context, entry, 'main').apply(compiler)
} else if (typeof entry === 'object') {
for (const name of Object.keys(entry)) {
this.itemToPlugin(context, entry[name], name).apply(compiler)
}
} else if (typeof entry === 'function') {
if (typeof entry === 'function') {
// TODO figure out why
throw new Error('not supported')
// new DynamicEntryPlugin(context, entry).apply(compiler)
} else{
for (const name of Object.keys(entry)) {
const desc = entry[name]
const options = BabelTargetEntryOptionPlugin.entryDescriptionToOptions(compiler, name, desc)
for (const entry of desc.import) {
new BabelTargetEntryPlugin(this.targets, context, entry, options).apply(compiler)
}
}
}
return true
})
Expand Down
22 changes: 15 additions & 7 deletions src/babel.target.entry.plugin.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,32 @@
import { Compiler, Plugin, Compilation, Dependency, NormalModuleFactory } from 'webpack'
import { Compiler, EntryPlugin, Compilation, Dependency, NormalModuleFactory } from 'webpack'

import { BabelTarget } from './babel-target'
import { BabelTargetSingleEntryDependency } from './babel.target.single.entry.dependency'
import { BabelTargetEntryDependency } from './babel.target.entry.dependency'

export abstract class BabelTargetEntryPlugin implements Plugin {

protected constructor(protected targets: BabelTarget[], protected context: string, protected name: string) {
}
export class BabelTargetEntryPlugin implements EntryPlugin {
public constructor(protected targets: BabelTarget[], public context: string,
public entry: string, public options: EntryPlugin['options']) {}

public apply(compiler: Compiler): void {
compiler.hooks.compilation.tap(
this.constructor.name,
(compilation: Compilation, { normalModuleFactory }: { normalModuleFactory: NormalModuleFactory }) => {
compilation.dependencyFactories.set(
BabelTargetSingleEntryDependency,
BabelTargetEntryDependency,
normalModuleFactory,
)
},
)

compiler.hooks.make.tapPromise(
this.constructor.name,
async (compilation: Compilation) => {
await Promise.all(this.targets.map(async target => {
const dep = new BabelTargetEntryDependency(target, this.entry, (this.options as any).name)
return await this.addEntry(compilation, dep)
}))
},
)
}

protected async addEntry(compilation: Compilation, dep: BabelTargetEntryDependency): Promise<void>
Expand Down
18 changes: 0 additions & 18 deletions src/babel.target.multi.entry.dependency.ts

This file was deleted.

0 comments on commit 484a2d7

Please sign in to comment.