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

Webpack vite compiler wip #1423

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/popular-cups-serve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@vanilla-extract/webpack-plugin': patch
'@vanilla-extract/integration': patch
---

Testing vite node compiler in webpack plugin
24 changes: 19 additions & 5 deletions packages/integration/src/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,10 @@ export interface Compiler {
filePath: string,
options?: {
outputCss?: boolean;
serializeVirtualCssPath?: (file: {
fileName: string;
source: string;
}) => string | Promise<string>;
},
): Promise<{ source: string; watchFiles: Set<string> }>;
getCssForFile(virtualCssFilePath: string): { filePath: string; css: string };
Expand All @@ -184,7 +188,11 @@ interface ProcessedVanillaFile {

export interface CreateCompilerOptions {
root: string;
cssImportSpecifier?: (filePath: string) => string;
cssImportSpecifier?: (
cssDepModuleId: string,
moduleId: string,
source: string,
) => string | Promise<string>;
identifiers?: IdentifierOption;
viteConfig?: ViteUserConfig;
/** @deprecated */
Expand Down Expand Up @@ -332,7 +340,9 @@ export const createCompiler = ({

const { cssDeps, watchFiles } = scanModule(moduleNode);

for (const cssDep of cssDeps) {
// Filter falsy css deps, webpack plugin's extracted.js file has undefined cssDeps for
// some reason
for (const cssDep of cssDeps.filter(Boolean)) {
const cssDepModuleId = normalizePath(cssDep);
const cssObjs = cssByModuleId.get(cssDepModuleId);
const cachedCss = cssCache.get(cssDepModuleId);
Expand All @@ -343,9 +353,9 @@ export const createCompiler = ({
continue;
}

if (cssObjs) {
let css = '';
let css = cachedCss?.css || '';

if (cssObjs) {
if (cssObjs.length > 0) {
css = transformCss({
localClassNames: Array.from(localClassNames),
Expand All @@ -368,7 +378,11 @@ export const createCompiler = ({

if (cssObjs || cachedCss?.css) {
cssImports.push(
`import '${cssImportSpecifier(cssDepModuleId)}';`,
`import '${await cssImportSpecifier(
cssDepModuleId,
moduleId,
css,
)}';`,
);
}
}
Expand Down
2 changes: 2 additions & 0 deletions packages/webpack-plugin-next/extracted.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// This is a noop file for extracted CSS source to point to
// Webpack requires a file to exist on disk for virtual source files
4 changes: 4 additions & 0 deletions packages/webpack-plugin-next/loader/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"main": "dist/vanilla-extract-webpack-plugin-next-loader.cjs.js",
"module": "dist/vanilla-extract-webpack-plugin-next-loader.esm.js"
}
4 changes: 4 additions & 0 deletions packages/webpack-plugin-next/next/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"main": "dist/vanilla-extract-webpack-plugin-next-next.cjs.js",
"module": "dist/vanilla-extract-webpack-plugin-next-next.esm.js"
}
74 changes: 74 additions & 0 deletions packages/webpack-plugin-next/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
{
"name": "@vanilla-extract/webpack-plugin-next",
"version": "0.0.0",
"description": "Zero-runtime Stylesheets-in-TypeScript",
"main": "dist/vanilla-extract-webpack-plugin-next.cjs.js",
"module": "dist/vanilla-extract-webpack-plugin-next.esm.js",
"types": "dist/vanilla-extract-webpack-plugin-next.cjs.d.ts",
"exports": {
"./package.json": "./package.json",
".": {
"types": "./dist/vanilla-extract-webpack-plugin-next.cjs.d.ts",
"module": "./dist/vanilla-extract-webpack-plugin-next.esm.js",
"default": "./dist/vanilla-extract-webpack-plugin-next.cjs.js"
},
"./loader": {
"types": "./loader/dist/vanilla-extract-webpack-plugin-next-loader.cjs.d.ts",
"module": "./loader/dist/vanilla-extract-webpack-plugin-next-loader.esm.js",
"default": "./loader/dist/vanilla-extract-webpack-plugin-next-loader.cjs.js"
},
"./virtualFileLoader": {
"types": "./virtualFileLoader/dist/vanilla-extract-webpack-plugin-next-virtualFileLoader.cjs.d.ts",
"module": "./virtualFileLoader/dist/vanilla-extract-webpack-plugin-next-virtualFileLoader.esm.js",
"default": "./virtualFileLoader/dist/vanilla-extract-webpack-plugin-next-virtualFileLoader.cjs.js"
},
"./next": {
"types": "./next/dist/vanilla-extract-webpack-plugin-next-next.cjs.d.ts",
"module": "./next/dist/vanilla-extract-webpack-plugin-next-next.esm.js",
"default": "./next/dist/vanilla-extract-webpack-plugin-next-next.cjs.js"
},
"./virtualNextFileLoader": {
"types": "./virtualNextFileLoader/dist/vanilla-extract-webpack-plugin-next-virtualNextFileLoader.cjs.d.ts",
"module": "./virtualNextFileLoader/dist/vanilla-extract-webpack-plugin-next-virtualNextFileLoader.esm.js",
"default": "./virtualNextFileLoader/dist/vanilla-extract-webpack-plugin-next-virtualNextFileLoader.cjs.js"
}
},
"preconstruct": {
"entrypoints": [
"index.ts",
"loader.ts",
"virtualFileLoader.ts",
"next.ts",
"virtualNextFileLoader.ts"
]
},
"files": [
"/dist",
"/loader",
"/virtualFileLoader",
"/next",
"/virtualNextFileLoader",
"extracted.js",
"vanilla.virtual.css"
],
"repository": {
"type": "git",
"url": "https://github.com/vanilla-extract-css/vanilla-extract.git",
"directory": "packages/webpack-plugin-next"
},
"author": "SEEK",
"license": "MIT",
"peerDependencies": {
"webpack": "^4.30.0 || ^5.20.2"
},
"dependencies": {
"@vanilla-extract/integration": "workspace:^",
"debug": "^4.3.1",
"loader-utils": "^2.0.0",
"picocolors": "^1.0.0"
},
"devDependencies": {
"@types/debug": "^4.1.5",
"webpack": "^5.90.0"
}
}
51 changes: 51 additions & 0 deletions packages/webpack-plugin-next/src/compat.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import {
Compiler,
ExternalsPlugin,
Compilation,
Module,
node,
optimize,
} from 'webpack';

export interface WebpackCompat {
isWebpack5: boolean;
getNodeTemplatePlugin: (compiler: Compiler) => typeof node.NodeTemplatePlugin;
getNodeTargetPlugin: (compiler: Compiler) => typeof node.NodeTargetPlugin;
getLimitChunkCountPlugin: (
compiler: Compiler,
) => typeof optimize.LimitChunkCountPlugin;
getExternalsPlugin: (compiler: Compiler) => typeof ExternalsPlugin;
isModuleUsed: (compilation: Compilation, module: Module) => boolean;
}

const webpack4: WebpackCompat = {
isWebpack5: false,
getNodeTemplatePlugin: () => require('webpack/lib/node/NodeTemplatePlugin'),
getNodeTargetPlugin: () => require('webpack/lib/node/NodeTargetPlugin'),
getLimitChunkCountPlugin: () =>
require('webpack/lib/optimize/LimitChunkCountPlugin'),
getExternalsPlugin: () => require('webpack/lib/ExternalsPlugin'),
isModuleUsed: (_compilation, module) =>
typeof module.used === 'boolean' ? module.used : true,
};

const webpack5: WebpackCompat = {
isWebpack5: true,
getNodeTemplatePlugin: (compiler) => compiler.webpack.node.NodeTemplatePlugin,
getNodeTargetPlugin: (compiler) => compiler.webpack.node.NodeTargetPlugin,
getLimitChunkCountPlugin: (compiler) =>
compiler.webpack.optimize.LimitChunkCountPlugin,
getExternalsPlugin: (compiler) => compiler.webpack.ExternalsPlugin,
isModuleUsed: (compilation, module) => {
const exportsInfo = compilation.moduleGraph.getExportsInfo(module);

return exportsInfo.isModuleUsed('main');
},
};

export default (isWebpack5: boolean): WebpackCompat => {
if (isWebpack5) {
return webpack5;
}
return webpack4;
};
8 changes: 8 additions & 0 deletions packages/webpack-plugin-next/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { Compiler } from 'webpack';
import { AbstractVanillaExtractPlugin } from './plugin';

export class VanillaExtractPlugin extends AbstractVanillaExtractPlugin {
apply(compiler: Compiler) {
this.inject(compiler, 'virtualFileLoader');
}
}
77 changes: 77 additions & 0 deletions packages/webpack-plugin-next/src/loader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// @ts-expect-error
import loaderUtils from 'loader-utils';
import {
getPackageInfo,
IdentifierOption,
transform,
type Compiler as VanillaExtractCompiler,
} from '@vanilla-extract/integration';

import type { LoaderContext } from './types';
import { debug, formatResourcePath } from './logger';
interface LoaderOptions {
outputCss: boolean;
identifiers?: IdentifierOption;
}

interface InternalLoaderOptions extends LoaderOptions {
vanillaExtractCompiler: VanillaExtractCompiler;
virtualLoader: 'virtualFileLoader' | 'virtualNextFileLoader';
}

const defaultIdentifierOption = (
mode: LoaderContext['mode'],
identifiers?: IdentifierOption,
): IdentifierOption =>
identifiers ?? (mode === 'production' ? 'short' : 'debug');

export default function (this: LoaderContext, source: string) {
const { identifiers } = loaderUtils.getOptions(this) as InternalLoaderOptions;

const { name } = getPackageInfo(this.rootContext);

const callback = this.async();

transform({
source,
filePath: this.resourcePath,
rootPath: this.rootContext,
packageName: name,
identOption: defaultIdentifierOption(this.mode, identifiers),
})
.then((code) => {
callback(null, code);
})
.catch((e) => {
callback(e);
});
}

export function pitch(this: LoaderContext) {
const { vanillaExtractCompiler, outputCss } = loaderUtils.getOptions(
this,
) as InternalLoaderOptions;

const log = debug(
`vanilla-extract:loader:${formatResourcePath(this.resourcePath)}`,
);

log(`Loading file ${this.resourcePath}`);

const callback = this.async();

vanillaExtractCompiler
.processVanillaFile(this.resourcePath, {
outputCss,
})
.then(({ source, watchFiles }) => {
watchFiles.forEach((dep) => {
this.addDependency(dep);
});
log(`Source:\n${source}`);
callback(null, source);
})
.catch((e) => {
callback(e);
});
}
9 changes: 9 additions & 0 deletions packages/webpack-plugin-next/src/logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import createDebug from 'debug';
import pc from 'picocolors';

export const formatResourcePath = (i: string) =>
pc.blue(`"${i.replace(/.*\//, '')}"`);

createDebug.formatters.r = (r: string) => formatResourcePath(r);

export const debug = createDebug;
18 changes: 18 additions & 0 deletions packages/webpack-plugin-next/src/next.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import path from 'path';
import { AbstractVanillaExtractPlugin } from './plugin';
import type { Compiler } from 'webpack';

const virtualNextFileLoader = require.resolve(
path.join(
path.dirname(require.resolve('../../package.json')),
'virtualNextFileLoader',
),
);

export class VanillaExtractPlugin extends AbstractVanillaExtractPlugin {
static loader = virtualNextFileLoader;

apply(compiler: Compiler) {
this.inject(compiler, 'virtualNextFileLoader');
}
}
Loading