stylex-webpack 0.1.1-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/index.d.ts +40 -0
- package/dist/index.js +150 -0
- package/dist/next.d.ts +32 -0
- package/dist/next.js +115 -0
- package/dist/stylex-loader.js +62 -0
- package/dist/stylex.virtual.css +7 -0
- package/package.json +80 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Sukka
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import webpack from 'webpack';
|
|
2
|
+
import { Options, Rule } from '@stylexjs/babel-plugin';
|
|
3
|
+
|
|
4
|
+
interface StyleXPluginOption {
|
|
5
|
+
stylexOption?: Partial<Options>;
|
|
6
|
+
/**
|
|
7
|
+
* Specify where to inject the StyleX generated CSS
|
|
8
|
+
*
|
|
9
|
+
* @default (filename) => filename.endsWith('stylex.css')
|
|
10
|
+
*/
|
|
11
|
+
appendTo?: (assetPath: string) => boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Specify where stylex will be imported from
|
|
14
|
+
*
|
|
15
|
+
* @default ['stylex', '@stylexjs/stylex']
|
|
16
|
+
*/
|
|
17
|
+
stylexImports?: string[];
|
|
18
|
+
/**
|
|
19
|
+
* Whether to use CSS layers
|
|
20
|
+
*
|
|
21
|
+
* @default false
|
|
22
|
+
*/
|
|
23
|
+
useCSSLayers?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Enable stylex's unstable_moduleResolution and specify rootDir
|
|
26
|
+
*/
|
|
27
|
+
rootDir?: string;
|
|
28
|
+
}
|
|
29
|
+
type RegisterStyleXRules = (resourcePath: string, stylexRules: Rule[]) => void;
|
|
30
|
+
declare class StyleXPlugin {
|
|
31
|
+
static stylexLoader: string;
|
|
32
|
+
stylexRules: Map<string, readonly Rule[]>;
|
|
33
|
+
readonly stylexImports: string[];
|
|
34
|
+
useCSSLayers: boolean;
|
|
35
|
+
stylexOption: Partial<Options>;
|
|
36
|
+
constructor({ stylexImports, useCSSLayers, stylexOption }?: StyleXPluginOption);
|
|
37
|
+
apply(compiler: webpack.Compiler): void;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export { type RegisterStyleXRules, StyleXPlugin, type StyleXPluginOption };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var stylexBabelPlugin = require('@stylexjs/babel-plugin');
|
|
4
|
+
var path = require('path');
|
|
5
|
+
|
|
6
|
+
const PLUGIN_NAME = 'stylex';
|
|
7
|
+
const VIRTUAL_CSS_PATH = require.resolve('./stylex.virtual.css');
|
|
8
|
+
const VIRTUAL_CSS_PATTERN = /stylex\.virtual\.css/;
|
|
9
|
+
// Webpack does not export these constants
|
|
10
|
+
// https://github.com/webpack/webpack/blob/b67626c7b4ffed8737d195b27c8cea1e68d58134/lib/OptimizationStages.js#L8
|
|
11
|
+
const OPTIMIZE_CHUNKS_STAGE_ADVANCED = 10;
|
|
12
|
+
|
|
13
|
+
function _define_property(obj, key, value) {
|
|
14
|
+
if (key in obj) {
|
|
15
|
+
Object.defineProperty(obj, key, {
|
|
16
|
+
value: value,
|
|
17
|
+
enumerable: true,
|
|
18
|
+
configurable: true,
|
|
19
|
+
writable: true
|
|
20
|
+
});
|
|
21
|
+
} else {
|
|
22
|
+
obj[key] = value;
|
|
23
|
+
}
|
|
24
|
+
return obj;
|
|
25
|
+
}
|
|
26
|
+
const stylexLoaderPath = require.resolve('./stylex-loader');
|
|
27
|
+
const getStyleXRules = (stylexRules, useCSSLayers)=>{
|
|
28
|
+
if (stylexRules.size === 0) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
// Take styles for the modules that were included in the last compilation.
|
|
32
|
+
const allRules = Array.from(stylexRules.values()).flat();
|
|
33
|
+
return stylexBabelPlugin.processStylexRules(allRules, useCSSLayers);
|
|
34
|
+
};
|
|
35
|
+
class StyleXPlugin {
|
|
36
|
+
apply(compiler) {
|
|
37
|
+
// If splitChunk is enabled, we create a dedicated chunk for stylex css
|
|
38
|
+
if (!compiler.options.optimization.splitChunks) {
|
|
39
|
+
throw new Error([
|
|
40
|
+
'You don\'t have "optimization.splitChunks" enabled.',
|
|
41
|
+
'"optimization.splitChunks" should be enabled for "stylex-webpack" to function properly.'
|
|
42
|
+
].join(' '));
|
|
43
|
+
}
|
|
44
|
+
// const IS_RSPACK = Object.prototype.hasOwnProperty.call(compiler.webpack, 'rspackVersion');
|
|
45
|
+
// stylex-loader adds virtual css import (which triggers virtual-loader)
|
|
46
|
+
// This prevents "stylex.virtual.css" files from being tree shaken by forcing
|
|
47
|
+
// "sideEffects" setting.
|
|
48
|
+
compiler.hooks.normalModuleFactory.tap(PLUGIN_NAME, (nmf)=>{
|
|
49
|
+
nmf.hooks.createModule.tap(PLUGIN_NAME, (createData)=>{
|
|
50
|
+
const modPath = createData.matchResource ?? createData.resourceResolveData?.path;
|
|
51
|
+
if (modPath === VIRTUAL_CSS_PATH) {
|
|
52
|
+
var _createData;
|
|
53
|
+
(_createData = createData).settings ?? (_createData.settings = {});
|
|
54
|
+
createData.settings.sideEffects = true;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
const { Compilation, NormalModule, sources } = compiler.webpack;
|
|
59
|
+
const { ConcatSource, RawSource } = sources;
|
|
60
|
+
// Apply loader to JS modules
|
|
61
|
+
compiler.hooks.make.tap(PLUGIN_NAME, (compilation)=>{
|
|
62
|
+
NormalModule.getCompilationHooks(compilation).loader.tap(PLUGIN_NAME, (loaderContext, mod)=>{
|
|
63
|
+
const extname = path.extname(mod.resource);
|
|
64
|
+
if (// JavaScript (and Flow) modules
|
|
65
|
+
/\.jsx?/.test(extname) || /\.tsx?/.test(extname)) {
|
|
66
|
+
loaderContext.StyleXWebpackContextKey = {
|
|
67
|
+
registerStyleXRules: (resourcePath, stylexRules)=>{
|
|
68
|
+
this.stylexRules.set(resourcePath, stylexRules);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
// We use .push() here instead of .unshift()
|
|
72
|
+
// Webpack usually runs loaders in reverse order and we want to ideally run
|
|
73
|
+
// our loader before anything else.
|
|
74
|
+
mod.loaders.push({
|
|
75
|
+
loader: stylexLoaderPath,
|
|
76
|
+
options: {
|
|
77
|
+
stylexImports: this.stylexImports,
|
|
78
|
+
stylexOption: this.stylexOption
|
|
79
|
+
},
|
|
80
|
+
ident: null,
|
|
81
|
+
type: null
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
// Create a "stylex" chunk to hold all collected virtual stylex css
|
|
86
|
+
// This eliminates the need for manually specify splitChunks.cacheGroups.stylex
|
|
87
|
+
compilation.hooks.optimizeChunks.tap({
|
|
88
|
+
name: PLUGIN_NAME,
|
|
89
|
+
stage: OPTIMIZE_CHUNKS_STAGE_ADVANCED
|
|
90
|
+
}, ()=>{
|
|
91
|
+
const stylexChunk = compilation.namedChunks.get('stylex') || compilation.addChunk('stylex');
|
|
92
|
+
const matchingChunks = new Set();
|
|
93
|
+
let moduleIndex = 0;
|
|
94
|
+
for (const module of compilation.modules){
|
|
95
|
+
const moduleName = module.nameForCondition();
|
|
96
|
+
if (module.type === 'css/mini-extract' && moduleName && VIRTUAL_CSS_PATTERN.test(moduleName)) {
|
|
97
|
+
const moduleChunks = compilation.chunkGraph.getModuleChunksIterable(module);
|
|
98
|
+
for (const chunk of moduleChunks){
|
|
99
|
+
compilation.chunkGraph.disconnectChunkAndModule(chunk, module);
|
|
100
|
+
for (const group of chunk.groupsIterable){
|
|
101
|
+
group.setModulePostOrderIndex(module, moduleIndex++);
|
|
102
|
+
}
|
|
103
|
+
matchingChunks.add(chunk);
|
|
104
|
+
}
|
|
105
|
+
compilation.chunkGraph.connectChunkAndModule(stylexChunk, module);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
for (const chunk of matchingChunks){
|
|
109
|
+
chunk.split(stylexChunk);
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
compilation.hooks.processAssets.tap({
|
|
113
|
+
name: PLUGIN_NAME,
|
|
114
|
+
stage: Compilation.PROCESS_ASSETS_STAGE_PRE_PROCESS
|
|
115
|
+
}, (assets)=>{
|
|
116
|
+
const cssFileName = Object.keys(assets).find((filename)=>filename.endsWith('stylex.css'));
|
|
117
|
+
if (cssFileName) {
|
|
118
|
+
const cssAsset = assets[cssFileName];
|
|
119
|
+
const stylexCSS = getStyleXRules(this.stylexRules, this.useCSSLayers);
|
|
120
|
+
if (stylexCSS != null) {
|
|
121
|
+
assets[cssFileName] = new ConcatSource(cssAsset, new RawSource(stylexCSS));
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
constructor({ stylexImports = [
|
|
128
|
+
'stylex',
|
|
129
|
+
'@stylexjs/stylex'
|
|
130
|
+
], useCSSLayers = false, stylexOption = {} } = {}){
|
|
131
|
+
_define_property(this, "stylexRules", new Map());
|
|
132
|
+
_define_property(this, "stylexImports", []);
|
|
133
|
+
_define_property(this, "useCSSLayers", void 0);
|
|
134
|
+
_define_property(this, "stylexOption", void 0);
|
|
135
|
+
this.useCSSLayers = useCSSLayers;
|
|
136
|
+
this.stylexOption = {
|
|
137
|
+
dev: process.env.NODE_ENV === 'development',
|
|
138
|
+
useRemForFontSize: true,
|
|
139
|
+
runtimeInjection: false,
|
|
140
|
+
genConditionalClasses: true,
|
|
141
|
+
treeshakeCompensation: true,
|
|
142
|
+
importSources: stylexImports,
|
|
143
|
+
...stylexOption
|
|
144
|
+
};
|
|
145
|
+
this.stylexImports = stylexImports;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
_define_property(StyleXPlugin, "stylexLoader", stylexLoaderPath);
|
|
149
|
+
|
|
150
|
+
exports.StyleXPlugin = StyleXPlugin;
|
package/dist/next.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { NextConfig } from 'next/dist/server/config-shared';
|
|
2
|
+
import { Options } from '@stylexjs/babel-plugin';
|
|
3
|
+
|
|
4
|
+
interface StyleXPluginOption {
|
|
5
|
+
stylexOption?: Partial<Options>;
|
|
6
|
+
/**
|
|
7
|
+
* Specify where to inject the StyleX generated CSS
|
|
8
|
+
*
|
|
9
|
+
* @default (filename) => filename.endsWith('stylex.css')
|
|
10
|
+
*/
|
|
11
|
+
appendTo?: (assetPath: string) => boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Specify where stylex will be imported from
|
|
14
|
+
*
|
|
15
|
+
* @default ['stylex', '@stylexjs/stylex']
|
|
16
|
+
*/
|
|
17
|
+
stylexImports?: string[];
|
|
18
|
+
/**
|
|
19
|
+
* Whether to use CSS layers
|
|
20
|
+
*
|
|
21
|
+
* @default false
|
|
22
|
+
*/
|
|
23
|
+
useCSSLayers?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Enable stylex's unstable_moduleResolution and specify rootDir
|
|
26
|
+
*/
|
|
27
|
+
rootDir?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
declare const _default: (pluginOptions?: StyleXPluginOption) => (nextConfig?: NextConfig) => NextConfig;
|
|
31
|
+
|
|
32
|
+
export { _default as default };
|
package/dist/next.js
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var nextMiniCssExtractPluginExports = require('next/dist/build/webpack/plugins/mini-css-extract-plugin');
|
|
4
|
+
var log = require('next/dist/build/output/log');
|
|
5
|
+
var index = require('./index');
|
|
6
|
+
|
|
7
|
+
require.resolve('./stylex.virtual.css');
|
|
8
|
+
const VIRTUAL_CSS_PATTERN = /stylex\.virtual\.css/;
|
|
9
|
+
|
|
10
|
+
/** Next.js' precompilation add "__esModule: true", but doesn't add an actual default exports */ // @ts-expect-error -- Next.js fucks something up
|
|
11
|
+
const NextMiniCssExtractPlugin = nextMiniCssExtractPluginExports.default;
|
|
12
|
+
const getNextMiniCssExtractPlugin = (isDev)=>{
|
|
13
|
+
// Use own MiniCssExtractPlugin to ensure HMR works
|
|
14
|
+
// v9 has issues when using own plugin in production
|
|
15
|
+
// v10.2.1 has issues when using built-in plugin in development since it
|
|
16
|
+
// doesn't bundle HMR files
|
|
17
|
+
// v12.1.7 finaly fixes the issue by adding the missing hmr/hotModuleReplacement.js file
|
|
18
|
+
if (isDev) {
|
|
19
|
+
try {
|
|
20
|
+
// Check if hotModuleReplacement exists
|
|
21
|
+
require('next/dist/compiled/mini-css-extract-plugin/hmr/hotModuleReplacement');
|
|
22
|
+
return NextMiniCssExtractPlugin;
|
|
23
|
+
} catch {
|
|
24
|
+
log.warn('Next.js built-in mini-css-extract-plugin is broken, will fallback to "mini-css-extract-plugin"');
|
|
25
|
+
return require('mini-css-extract-plugin');
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// Always use Next.js built-in MiniCssExtractPlugin in production
|
|
29
|
+
return NextMiniCssExtractPlugin;
|
|
30
|
+
};
|
|
31
|
+
// Adopt from Next.js' getGlobalCssLoader
|
|
32
|
+
// https://github.com/vercel/next.js/blob/d61b0761efae09bd9cb1201ff134ed8950d9deca/packages/next/src/build/webpack/config/blocks/css/loaders/global.ts#L7
|
|
33
|
+
function getStyleXVirtualCssLoader(options, MiniCssExtractPlugin) {
|
|
34
|
+
const loaders = [];
|
|
35
|
+
// Adopt from Next.js' getClientStyleLoader
|
|
36
|
+
// https://github.com/vercel/next.js/blob/56d35ede8ed2ab25fa8e29583d4e81e3e76a0e29/packages/next/src/build/webpack/config/blocks/css/loaders/global.ts#L7
|
|
37
|
+
if (!options.isServer) {
|
|
38
|
+
// https://github.com/vercel/next.js/blob/56d35ede8ed2ab25fa8e29583d4e81e3e76a0e29/packages/next/src/build/webpack/config/blocks/css/loaders/global.ts#L18
|
|
39
|
+
// https://github.com/vercel/next.js/blob/56d35ede8ed2ab25fa8e29583d4e81e3e76a0e29/packages/next/src/build/webpack/config/blocks/css/loaders/client.ts#L3
|
|
40
|
+
loaders.push({
|
|
41
|
+
loader: MiniCssExtractPlugin.loader,
|
|
42
|
+
options: {
|
|
43
|
+
publicPath: `${options.assetPrefix}/_next/`,
|
|
44
|
+
esModule: false
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
return loaders;
|
|
49
|
+
}
|
|
50
|
+
module.exports = (pluginOptions)=>(nextConfig = {})=>{
|
|
51
|
+
return {
|
|
52
|
+
...nextConfig,
|
|
53
|
+
webpack (config, ctx) {
|
|
54
|
+
var // For some reason, Next 11.0.1 has `config.optimization.splitChunks`
|
|
55
|
+
// set to `false` when webpack 5 is enabled.
|
|
56
|
+
_config_optimization, _config_optimization_splitChunks;
|
|
57
|
+
if (typeof nextConfig.webpack === 'function') {
|
|
58
|
+
config = nextConfig.webpack(config, ctx);
|
|
59
|
+
}
|
|
60
|
+
(_config_optimization = config.optimization).splitChunks || (_config_optimization.splitChunks = {});
|
|
61
|
+
(_config_optimization_splitChunks = config.optimization.splitChunks).cacheGroups || (_config_optimization_splitChunks.cacheGroups = {});
|
|
62
|
+
const MiniCssExtractPlugin = getNextMiniCssExtractPlugin(ctx.dev);
|
|
63
|
+
// Based on https://github.com/vercel/next.js/blob/88a5f263f11cb55907f0d89a4cd53647ee8e96ac/packages/next/build/webpack/config/helpers.ts#L12-L18
|
|
64
|
+
const cssRules = config.module.rules.find((rule)=>Array.isArray(rule.oneOf) && rule.oneOf.some(({ test })=>typeof test === 'object' && typeof test.test === 'function' && test.test('filename.css'))).oneOf;
|
|
65
|
+
// Here we matches virtual css file emitted by Style9Plugin
|
|
66
|
+
cssRules.unshift({
|
|
67
|
+
test: VIRTUAL_CSS_PATTERN,
|
|
68
|
+
use: getStyleXVirtualCssLoader(ctx, MiniCssExtractPlugin)
|
|
69
|
+
});
|
|
70
|
+
// StyleX need to emit the css file on both server and client, both during the
|
|
71
|
+
// development and production.
|
|
72
|
+
// However, Next.js only add MiniCssExtractPlugin on client + production.
|
|
73
|
+
//
|
|
74
|
+
// To simplify the logic at our side, we will add MiniCssExtractPlugin based on
|
|
75
|
+
// the "instanceof" check (We will only add our required MiniCssExtractPlugin if
|
|
76
|
+
// Next.js hasn't added it yet).
|
|
77
|
+
// This also prevent multiple MiniCssExtractPlugin being added (which will cause
|
|
78
|
+
// RealContentHashPlugin to panic)
|
|
79
|
+
if (!config.plugins.some((plugin)=>plugin instanceof MiniCssExtractPlugin)) {
|
|
80
|
+
// HMR reloads the CSS file when the content changes but does not use
|
|
81
|
+
// the new file name, which means it can't contain a hash.
|
|
82
|
+
const filename = ctx.dev ? 'static/css/[name].css' : 'static/css/[contenthash].css';
|
|
83
|
+
// Logic adopted from https://git.io/JtdBy
|
|
84
|
+
config.plugins.push(new MiniCssExtractPlugin({
|
|
85
|
+
filename,
|
|
86
|
+
chunkFilename: filename,
|
|
87
|
+
// Next.js guarantees that CSS order "doesn't matter", due to imposed
|
|
88
|
+
// restrictions:
|
|
89
|
+
// 1. Global CSS can only be defined in a single entrypoint (_app)
|
|
90
|
+
// 2. CSS Modules generate scoped class names by default and cannot
|
|
91
|
+
// include Global CSS (:global() selector).
|
|
92
|
+
//
|
|
93
|
+
// While not a perfect guarantee (e.g. liberal use of `:global()`
|
|
94
|
+
// selector), this assumption is required to code-split CSS.
|
|
95
|
+
//
|
|
96
|
+
// As for StyleX, the CSS is always atomic (so classes are always unique),
|
|
97
|
+
// and StyleX Plugin will always sort the css based on media query and pseudo
|
|
98
|
+
// selector.
|
|
99
|
+
//
|
|
100
|
+
// If this warning were to trigger, it'd be unactionable by the user,
|
|
101
|
+
// but likely not valid -- so just disable it.
|
|
102
|
+
ignoreOrder: true
|
|
103
|
+
}));
|
|
104
|
+
}
|
|
105
|
+
config.plugins.push(new index.StyleXPlugin({
|
|
106
|
+
...pluginOptions,
|
|
107
|
+
stylexOption: {
|
|
108
|
+
...pluginOptions?.stylexOption,
|
|
109
|
+
dev: ctx.dev
|
|
110
|
+
}
|
|
111
|
+
}));
|
|
112
|
+
return config;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var core = require('@babel/core');
|
|
4
|
+
var stylexBabelPlugin = require('@stylexjs/babel-plugin');
|
|
5
|
+
|
|
6
|
+
function stringifyRequest(loaderContext, request) {
|
|
7
|
+
return JSON.stringify(loaderContext.utils.contextify(loaderContext.context || loaderContext.rootContext, request));
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const VIRTUAL_CSS_PATH = require.resolve('./stylex.virtual.css');
|
|
11
|
+
const isSupplementedLoaderContext = (context)=>{
|
|
12
|
+
// eslint-disable-next-line prefer-object-has-own -- target older
|
|
13
|
+
return Object.prototype.hasOwnProperty.call(context, 'StyleXWebpackContextKey');
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const PLUGIN_NAME = 'stylex';
|
|
17
|
+
async function stylexLoader(inputCode, inputSourceMap) {
|
|
18
|
+
const callback = this.async();
|
|
19
|
+
const { stylexImports, stylexOption } = this.getOptions();
|
|
20
|
+
// bail out early if the input doesn't contain stylex imports
|
|
21
|
+
if (!stylexImports.some((importName)=>inputCode.includes(importName))) {
|
|
22
|
+
return callback(null, inputCode, inputSourceMap);
|
|
23
|
+
}
|
|
24
|
+
if (!isSupplementedLoaderContext(this)) {
|
|
25
|
+
return callback(new Error('stylex-loader: loader context is not SupplementedLoaderContext!'));
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
const { code, map, metadata } = await core.transformAsync(inputCode, {
|
|
29
|
+
babelrc: false,
|
|
30
|
+
inputSourceMap,
|
|
31
|
+
sourceFileName: this.resourcePath,
|
|
32
|
+
filename: this.resourcePath,
|
|
33
|
+
parserOpts: {
|
|
34
|
+
plugins: /\.tsx?$/.test(this.resourcePath) ? [
|
|
35
|
+
'typescript',
|
|
36
|
+
'jsx'
|
|
37
|
+
] : [
|
|
38
|
+
'jsx'
|
|
39
|
+
]
|
|
40
|
+
},
|
|
41
|
+
plugins: [
|
|
42
|
+
stylexBabelPlugin.withOptions(stylexOption)
|
|
43
|
+
]
|
|
44
|
+
});
|
|
45
|
+
const logger = this._compiler?.getInfrastructureLogger(PLUGIN_NAME);
|
|
46
|
+
// If metadata.stylex doesn't exist at all, we only need to return the transformed code
|
|
47
|
+
if (!metadata || !('stylex' in metadata) || metadata.stylex == null) {
|
|
48
|
+
logger?.debug(`No stylex styles generated from ${this.resourcePath}`);
|
|
49
|
+
return callback(null, code ?? undefined, map ?? undefined);
|
|
50
|
+
}
|
|
51
|
+
// this.stylexRules[filename] = metadata.stylex;
|
|
52
|
+
logger?.debug(`Read stylex styles from ${this.resourcePath}:`, metadata.stylex);
|
|
53
|
+
this.StyleXWebpackContextKey.registerStyleXRules(this.resourcePath, metadata.stylex);
|
|
54
|
+
const virtualCssRequest = stringifyRequest(this, `${VIRTUAL_CSS_PATH}?${JSON.stringify(metadata.stylex)}`);
|
|
55
|
+
const postfix = `\nimport ${virtualCssRequest};`;
|
|
56
|
+
return callback(null, code + postfix, map ?? undefined);
|
|
57
|
+
} catch (error) {
|
|
58
|
+
return callback(error);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
module.exports = stylexLoader;
|
package/package.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "stylex-webpack",
|
|
3
|
+
"version": "0.1.1-beta.1",
|
|
4
|
+
"description": "The another Webpack Plugin for Facebook's StyleX",
|
|
5
|
+
"homepage": "https://github.com/SukkaW/style9-webpack#readme",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/SukkaW/stylex-webpack.git"
|
|
9
|
+
},
|
|
10
|
+
"bugs": {
|
|
11
|
+
"url": "https://github.com/SukkaW/style9-webpack/issues"
|
|
12
|
+
},
|
|
13
|
+
"main": "dist/index.js",
|
|
14
|
+
"types": "dist/index.d.ts",
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"next.js"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "rollup -c rollup.config.ts --configPlugin swc3 --bundleConfigAsCjs",
|
|
21
|
+
"prerelease": "npm run build",
|
|
22
|
+
"lint": "eslint --format=sukka .",
|
|
23
|
+
"test": "mocha --require @swc-node/register test/index.ts",
|
|
24
|
+
"test:update": "mocha --update --require @swc-node/register test/index.ts",
|
|
25
|
+
"release": "bumpp -r --all --commit=\"release: %s\" --tag=\"%s\""
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"css",
|
|
29
|
+
"atomic-css",
|
|
30
|
+
"stylex",
|
|
31
|
+
"css-in-js",
|
|
32
|
+
"webpack",
|
|
33
|
+
"nextjs",
|
|
34
|
+
"app-router"
|
|
35
|
+
],
|
|
36
|
+
"author": "Sukka <https://skk.moe>",
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@babel/core": "^7.23.9",
|
|
40
|
+
"@babel/plugin-syntax-jsx": "^7.23.3",
|
|
41
|
+
"@babel/plugin-syntax-typescript": "^7.23.3",
|
|
42
|
+
"@stylexjs/babel-plugin": "^0.5.1",
|
|
43
|
+
"loader-utils": "^3.2.1"
|
|
44
|
+
},
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@eslint-sukka/node": "^5.1.0",
|
|
47
|
+
"@eslint-sukka/ts": "^5.1.0",
|
|
48
|
+
"@swc-node/register": "^1.8.0",
|
|
49
|
+
"@swc/core": "^1.4.1",
|
|
50
|
+
"@types/babel__core": "^7.20.5",
|
|
51
|
+
"@types/chai": "^4.3.11",
|
|
52
|
+
"@types/loader-utils": "^2.0.6",
|
|
53
|
+
"@types/mocha": "^10.0.6",
|
|
54
|
+
"@types/node": "^20.11.17",
|
|
55
|
+
"bumpp": "^9.3.0",
|
|
56
|
+
"chai": "^4.4.1",
|
|
57
|
+
"css-loader": "^6.10.0",
|
|
58
|
+
"eslint": "^8.56.0",
|
|
59
|
+
"eslint-config-sukka": "^5.1.0",
|
|
60
|
+
"eslint-formatter-sukka": "^5.1.0",
|
|
61
|
+
"memfs": "^4.7.0",
|
|
62
|
+
"mini-css-extract-plugin": "^2.8.0",
|
|
63
|
+
"mocha": "^10.3.0",
|
|
64
|
+
"mocha-chai-jest-snapshot": "^1.1.4",
|
|
65
|
+
"next": "^14.1.0",
|
|
66
|
+
"rollup": "^4.10.0",
|
|
67
|
+
"rollup-plugin-copy": "^3.5.0",
|
|
68
|
+
"rollup-plugin-dts": "^6.1.0",
|
|
69
|
+
"rollup-plugin-swc3": "^0.11.0",
|
|
70
|
+
"swc-loader": "^0.2.6",
|
|
71
|
+
"typescript": "^5.3.3",
|
|
72
|
+
"webpack": "^5.90.1"
|
|
73
|
+
},
|
|
74
|
+
"peerDependencies": {
|
|
75
|
+
"@stylexjs/stylex": "*"
|
|
76
|
+
},
|
|
77
|
+
"overrides": {
|
|
78
|
+
"chai": "$chai"
|
|
79
|
+
}
|
|
80
|
+
}
|