Skip to content

Commit

Permalink
feat: virtual module support for webpack
Browse files Browse the repository at this point in the history
  • Loading branch information
antfu committed Aug 25, 2021
1 parent 7fb7bb3 commit 333717b
Show file tree
Hide file tree
Showing 13 changed files with 155 additions and 26 deletions.
8 changes: 4 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
.DS_STORE
.profile
.vscode
node_modules
*.log*
dist
coverage
.profile
dist
node_modules
temp
dist-*
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@
],
"scripts": {
"build": "siroc build",
"dev": "siroc dev",
"lint": "eslint --ext ts .",
"release": "yarn test && yarn build && standard-version && yarn publish && git push --follow-tags",
"test:build:fixtures": "jiti scripts/buildFixtures.ts",
"test": "yarn lint && yarn test:build:fixtures && jest"
"test:build": "jiti scripts/buildFixtures.ts",
"test": "yarn lint && yarn test:build && jest"
},
"dependencies": {
"webpack-virtual-modules": "^0.4.3"
Expand All @@ -38,6 +39,7 @@
"@types/jest": "^27.0.1",
"@types/node": "^16.7.1",
"babel-loader": "^8.2.2",
"chalk": "^4.1.2",
"enhanced-resolve": "^5.8.2",
"eslint": "^7.32.0",
"fast-glob": "^3.2.7",
Expand Down
26 changes: 16 additions & 10 deletions scripts/buildFixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,27 @@
import { resolve, join } from 'path'
import { execSync } from 'child_process'
import fs from 'fs-extra'
import c from 'chalk'

async function run () {
const dir = resolve(__dirname, '../test/fixtures')
const fixtures = (await fs.readdir(dir)).map(i => resolve(dir, i))
let fixtures = await fs.readdir(dir)

for (const f of fixtures) {
if (fs.existsSync(join(f, 'dist'))) {
await fs.remove(join(f, 'dist'))
if (process.argv[2]) {
fixtures = fixtures.filter(i => i.includes(process.argv[2]))
}

for (const name of fixtures) {
const path = join(dir, name)
if (fs.existsSync(join(path, 'dist'))) {
await fs.remove(join(path, 'dist'))
}
console.log('\n====[Vite]====\n')
execSync('npx vite build', { cwd: f, stdio: 'inherit' })
console.log('\n====[Rollup]====\n')
execSync('npx rollup -c', { cwd: f, stdio: 'inherit' })
console.log('\n====[Webpack]====\n')
execSync('npx webpack', { cwd: f, stdio: 'inherit' })
console.log(c.yellow.inverse.bold`\n Vite `, name, '\n')
execSync('npx vite build', { cwd: path, stdio: 'inherit' })
console.log(c.red.inverse.bold`\n Rollup `, name, '\n')
execSync('npx rollup -c', { cwd: path, stdio: 'inherit' })
console.log(c.blue.inverse.bold`\n Webpack `, name, '\n')
execSync('npx webpack', { cwd: path, stdio: 'inherit' })
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export interface UnpluginOptions {
transformInclude?: (id: string) => boolean;
transform?: (this: UnpluginContext, code: string, id: string) => Thenable<string | { code: string; map: any; } | null | undefined>;
load?: (this: UnpluginContext, id?:string) => Thenable<string | null | undefined>
resolveId?: (id?:string) => Thenable<string | null | undefined>
resolveId?: (id: string, importer?: string) => Thenable<string | null | undefined>

// framework specify extends
rollup?: Partial<RollupPlugin>
Expand Down
23 changes: 15 additions & 8 deletions src/webpack/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { Resolver } from 'enhanced-resolve'
import VirtualModulesPlugin from 'webpack-virtual-modules'
import { UnpluginContextMeta } from '../context'
import type { UnpluginInstance, UnpluginFactory, WebpackCompiler, ResolvedUnpluginOptions } from '../types'
import { UNPLUGIN_VMOD_PREFIX } from './meta'

export function getWebpackPlugin<UserOptions = {}> (
factory: UnpluginFactory<UserOptions>
Expand Down Expand Up @@ -59,8 +60,14 @@ export function getWebpackPlugin<UserOptions = {}> (
const resolver = {
apply (resolver: Resolver) {
const tap = (target: any) => async (request: any, resolveContext: any, callback: any) => {
const resolved = await plugin.resolveId!(request.request)
if (!request.request || request.request.startsWith(UNPLUGIN_VMOD_PREFIX)) {
return callback()
}
let resolved = await plugin.resolveId!(request.request)
if (resolved != null) {
if (resolved === request.request) {
resolved = UNPLUGIN_VMOD_PREFIX + request.request
}
const newRequest = {
...request,
request: resolved
Expand All @@ -74,20 +81,20 @@ export function getWebpackPlugin<UserOptions = {}> (
}
}

resolver
.getHook('described-resolve')
.tapAsync('unplugin', tap(resolver.ensureHook('internal-resolve')))
// resolver
// .getHook('described-resolve')
// .tapAsync('unplugin', tap(resolver.ensureHook('internal-resolve')))
resolver
.getHook('resolve')
.tapAsync('unplugin', tap(resolver.ensureHook('resolve')))
resolver
.getHook('file')
.tapAsync('unplugin', tap(resolver.ensureHook('internal-resolve')))
// resolver
// .getHook('file')
// .tapAsync('unplugin', tap(resolver.ensureHook('internal-resolve')))
}
}

compiler.options.resolve.plugins = compiler.options.resolve.plugins || []
compiler.options.resolve.plugins.unshift(resolver)
compiler.options.resolve.plugins.push(resolver)
}

// TODO: not working for virtual module
Expand Down
9 changes: 8 additions & 1 deletion src/webpack/loaders/load.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { LoaderContext } from 'webpack'
import { UnpluginContext } from '../../context'
import { UNPLUGIN_VMOD_PREFIX } from '../meta'
import '../../types'

export default async function load (this: LoaderContext<any>, source: string) {
Expand All @@ -15,7 +16,13 @@ export default async function load (this: LoaderContext<any>, source: string) {
error: error => this.emitError(typeof error === 'string' ? new Error(error) : error),
warn: error => this.emitWarning(typeof error === 'string' ? new Error(error) : error)
}
const res = await plugin.load.call(context, this.resource)

let id = this.resource
if (id.startsWith(UNPLUGIN_VMOD_PREFIX)) {
id = id.slice(UNPLUGIN_VMOD_PREFIX.length)
}

const res = await plugin.load.call(context, id)

if (res == null) {
callback(null, source)
Expand Down
1 change: 1 addition & 0 deletions src/webpack/meta.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const UNPLUGIN_VMOD_PREFIX = '/__unplugin__/'
27 changes: 27 additions & 0 deletions test/fixtures/virtual-module/__test__/build.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { resolve } from 'path'
import fs from 'fs-extra'

const r = (...args: string[]) => resolve(__dirname, '../dist', ...args)

describe('virtual-module build', () => {
it('vite', async () => {
const content = await fs.readFile(r('vite/main.js.es.js'), 'utf-8')

expect(content).toContain('VIRTUAL:ONE')
expect(content).toContain('VIRTUAL:TWO')
})

it('rollup', async () => {
const content = await fs.readFile(r('rollup/main.js'), 'utf-8')

expect(content).toContain('VIRTUAL:ONE')
expect(content).toContain('VIRTUAL:TWO')
})

it('webpack', async () => {
const content = await fs.readFile(r('webpack/main.js'), 'utf-8')

expect(content).toContain('VIRTUAL:ONE')
expect(content).toContain('VIRTUAL:TWO')
})
})
11 changes: 11 additions & 0 deletions test/fixtures/virtual-module/rollup.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const { rollup } = require('./unplugin')

export default {
input: './src/main.js',
output: {
dir: './dist/rollup'
},
plugins: [
rollup()
]
}
4 changes: 4 additions & 0 deletions test/fixtures/virtual-module/src/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import msg1 from 'virtual-1'
import msg2 from 'virtual-2'

console.log(msg1, msg2)
19 changes: 19 additions & 0 deletions test/fixtures/virtual-module/unplugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const { createUnplugin } = require('unplugin')

module.exports = createUnplugin(() => {
return {
name: 'virtual-module-fixture',
resolveId (id) {
return id.startsWith('virtual-') ? id : null
},
load (id) {
if (id === 'virtual-1') {
return 'export default "VIRTUAL:ONE"'
}
if (id === 'virtual-2') {
return 'export default "VIRTUAL:TWO"'
}
return null
}
}
})
17 changes: 17 additions & 0 deletions test/fixtures/virtual-module/vite.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
const { resolve } = require('path')
const { vite } = require('./unplugin')

module.exports = {
root: __dirname,
plugins: [
vite()
],
build: {
lib: {
entry: resolve(__dirname, 'src/main.js'),
name: 'main',
fileName: 'main.js'
},
outDir: 'dist/vite'
}
}
28 changes: 28 additions & 0 deletions test/fixtures/virtual-module/webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
const { resolve } = require('path')
const { webpack } = require('./unplugin')

module.exports = {
mode: 'development',
entry: resolve(__dirname, 'src/main.js'),
output: {
path: resolve(__dirname, 'dist/webpack'),
filename: 'main.js'
},
plugins: [
webpack()
],
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/,
options: {
presets: [
'@babel/preset-env'
]
}
}
]
}
}

0 comments on commit 333717b

Please sign in to comment.