fix: style loading

This commit is contained in:
cha0s 2024-01-11 05:04:52 -06:00
parent f438c84615
commit 81fc5f633f
5 changed files with 48 additions and 43 deletions

View File

@ -1,11 +1,6 @@
const {join} = require('path');
module.exports = {
babel: {
plugins: [
join(__dirname, '..', 'src', 'server', 'style-loader'),
],
},
stubs: {
server: [
/\.(c|s[ac])ss$/,

View File

@ -11,7 +11,8 @@ const augmentBuild = (target, config, env, argv, flecks) => {
break;
}
case 'server': {
finalLoader = {loader: 'style-loader', options: {injectType: 'lazyStyleTag'}};
finalLoader = {loader: MiniCssExtractPlugin.loader, options: {emit: false}};
config.plugins.push(new MiniCssExtractPlugin({filename: 'assets/[name].css'}));
break;
}
case 'web': {
@ -44,7 +45,9 @@ const augmentBuild = (target, config, env, argv, flecks) => {
loaders,
{
modules: {
localIdentName: '[hash:4]',
localIdentName: isProduction
? '[hash:base64:5]'
: '[path][name]__[local]',
},
},
),

View File

@ -6,9 +6,6 @@
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title><%= htmlWebpackPlugin.options.title %></title>
<%= htmlWebpackPlugin.tags.headTags %>
<% styleFiles.forEach(({content, href}) => { %>
<style data-href="<%= href %>"><%= content %></style>
<% }); %>
</head>
<body>
<%= htmlWebpackPlugin.tags.bodyTags %>

View File

@ -8,6 +8,7 @@ const {
} = require('@flecks/core/server');
const AddAssetHtmlPlugin = require('add-asset-html-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const {htmlTagObjectToString} = require('html-webpack-plugin/lib/html-tags');
const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
const runtime = require('./runtime');
@ -79,17 +80,43 @@ module.exports = async (env, argv, flecks) => {
lang: 'en',
template: flecks.buildConfig('template.ejs', name),
templateParameters: (compilation, assets, assetTags, options) => {
const styleFiles = [];
const styleChunk = Array.from(compilation.chunks).find((chunk) => (
chunk.chunkReason?.match(/split chunk \(cache group: styles\)/)
));
if (isProduction && styleChunk) {
for (let i = 0; i < assets.css.length; ++i) {
const asset = compilation.assets[assets.css[i].substring(1)];
if (asset) {
styleFiles.push({content: asset.source(), href: assets.css[i]});
assetTags.headTags = assetTags.headTags
.filter(({attributes}) => attributes?.href !== assets.css[i]);
if ('index' === name) {
const styleChunks = Array.from(compilation.chunks)
.filter((chunk) => chunk.idNameHints.has('flecksCompiled'));
for (let i = 0; i < styleChunks.length; ++i) {
const styleChunk = styleChunks[i];
const styleChunkFiles = Array.from(styleChunk.files)
.filter((file) => file.match(/\.css$/));
const styleAssets = styleChunkFiles.map((filename) => compilation.assets[filename]);
for (let j = 0; j < styleAssets.length; ++j) {
const asset = styleAssets[j];
if (asset) {
assetTags.headTags = assetTags.headTags
.filter(({attributes}) => attributes?.href !== styleChunkFiles[j]);
let tag;
if (isProduction) {
tag = HtmlWebpackPlugin.createHtmlTagObject(
'style',
{'data-href': `/${styleChunkFiles[j]}`},
asset.source(),
{plugin: '@flecks/web/server'},
);
}
else {
tag = HtmlWebpackPlugin.createHtmlTagObject(
'link',
{
href: `/${styleChunkFiles[j]}`,
rel: 'stylesheet',
type: 'text/css',
},
undefined,
{plugin: '@flecks/web/server'},
);
}
tag.toString = () => htmlTagObjectToString(tag, false);
assetTags.headTags.unshift(tag);
}
}
}
}
@ -101,7 +128,6 @@ module.exports = async (env, argv, flecks) => {
files: assets,
options,
},
styleFiles,
};
},
title: id,
@ -152,13 +178,16 @@ module.exports = async (env, argv, flecks) => {
runtimeChunk: 'single',
splitChunks: {
cacheGroups: {
styles: {
applicationStyles: {
chunks: 'all',
type: 'css/mini-extract',
enforce: true,
name: 'applicationStyles',
priority: 100,
test: styleExtensionsRegex,
test: 'index',
},
},
chunks: 'all',
},
},
output: {

View File

@ -1,19 +0,0 @@
const parser = require('@babel/parser');
const types = require('@babel/types');
// On the server we use `lazyStyleTag` to avoid either dying over the lack of `document` or the
// inefficiency of extracting styles needlessly. When importing CSS modules, `lazyStyleTag` moves
// the default export into a named `locals` export. This babel plugin injects a small amount of
// code after the import in order to hide that from client code.
module.exports = () => ({
visitor: {
ImportDeclaration(path) {
if (path.node.source.value.match(/\.module\.(c|s[ac])ss$/)) {
const defaultSpecifier = path.node.specifiers.find(types.isImportDefaultSpecifier);
const {name} = defaultSpecifier.local;
defaultSpecifier.local.name = `${name}__default`;
path.insertAfter(parser.parse(`const ${name} = ${name}__default?.locals || ${name}__default`));
}
},
},
});