Possible example of babel-plugin-react-css-modules ipo isomorphic-style-loader ?
See original GitHub issueI’m trying to get babel-plugin-css-modules wired up but I’m a bit lost now 🗡
The page loads and the proper transformation is happening:
I see the class properly configured:
Page-container-QOUG7
for instance,
Matches the Page.css coming from source maps
// Page.css
exports.locals = {
"root": "Page-root-2VuHt",
"container": "Page-container-QOUG7"
};
I think whats not actually happening is the CSS isn’t getting injected into the page(style)
I’ve tried just about everything:
// package.json
"plugins": [
[
"react-css-modules",
{
"removeImport": true,
"generateScopedName": "[name]-[local]-[hash:base64:5]"
}
]
],
// webpack.config.js
import path from 'path';
import webpack from 'webpack';
import AssetsPlugin from 'assets-webpack-plugin';
import nodeExternals from 'webpack-node-externals';
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';
import overrideRules from './lib/overrideRules';
import pkg from '../package.json';
const isDebug = !process.argv.includes('--release');
const isVerbose = process.argv.includes('--verbose');
const isAnalyze =
process.argv.includes('--analyze') || process.argv.includes('--analyse');
const reScript = /\.m?jsx?$/;
const reStyle = /\.(css|less|scss|sss)$/;
const reImage = /\.(bmp|gif|jpe?g|png|svg)$/;
const staticAssetName = isDebug
? '[path][name].[ext]?[hash:8]'
: '[hash:8].[ext]';
//
// Common configuration chunk to be used for both
// client-side (client.js) and server-side (server.js) bundles
// -----------------------------------------------------------------------------
const config = {
context: path.resolve(__dirname, '..'),
output: {
path: path.resolve(__dirname, '../build/public/assets'),
publicPath: '/assets/',
pathinfo: isVerbose,
filename: isDebug ? '[name].js' : '[name].[chunkhash:8].js',
chunkFilename: isDebug
? '[name].chunk.js'
: '[name].[chunkhash:8].chunk.js',
devtoolModuleFilenameTemplate: info =>
path.resolve(info.absoluteResourcePath),
},
resolve: {
// Allow absolute paths in imports, e.g. import Button from 'components/Button'
// Keep in sync with .flowconfig and .eslintrc
modules: ['node_modules', 'src'],
},
module: {
// Make missing exports an error instead of warning
strictExportPresence: true,
rules: [
// Rules for JS / JSX
{
test: reScript,
include: path.resolve(__dirname, '../src'),
loader: 'babel-loader',
options: {
// https://github.com/babel/babel-loader#options
cacheDirectory: isDebug,
// https://babeljs.io/docs/usage/options/
babelrc: false,
presets: [
// A Babel preset that can automatically determine the Babel plugins and polyfills
// https://github.com/babel/babel-preset-env
[
'env',
{
targets: {
browsers: pkg.browserslist,
uglify: true,
},
modules: false,
useBuiltIns: false,
debug: false,
},
],
// Experimental ECMAScript proposals
// https://babeljs.io/docs/plugins/#presets-stage-x-experimental-presets-
'stage-2',
// JSX, Flow
// https://github.com/babel/babel/tree/master/packages/babel-preset-react
'react',
// Optimize React code for the production build
// https://github.com/thejameskyle/babel-react-optimize
...(isDebug ? [] : ['react-optimize']),
],
plugins: [
// Adds component stack to warning messages
// https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-react-jsx-source
...(isDebug ? ['transform-react-jsx-source'] : []),
// Adds __self attribute to JSX which React will use for some warnings
// https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-react-jsx-self
...(isDebug ? ['transform-react-jsx-self'] : []),
[
'react-css-modules',
{
// removeImport: true,
generateScopedName: '[name]-[local]-[hash:base64:5]',
},
],
],
},
},
// Rules for Style Sheets
{
test: reStyle,
rules: [
// // Convert CSS into JS module
// {
// issuer: { not: [reStyle] },
// use: 'isomorphic-style-loader',
// },
// Process external/third-party styles
{
exclude: path.resolve(__dirname, '../src'),
loader: 'css-loader',
options: {
sourceMap: isDebug,
minimize: !isDebug,
discardComments: { removeAll: true },
},
},
// Process internal/project styles (from src folder)
{
include: path.resolve(__dirname, '../src'),
loader: 'css-loader',
options: {
// CSS Loader https://github.com/webpack/css-loader
importLoaders: 1,
sourceMap: isDebug,
// CSS Modules https://github.com/css-modules/css-modules
modules: true,
localIdentName: '[name]-[local]-[hash:base64:5]',
// CSS Nano http://cssnano.co/options/
minimize: !isDebug,
discardComments: { removeAll: true },
},
},
// Apply PostCSS plugins including autoprefixer
{
loader: 'postcss-loader',
options: {
config: {
path: './tools/postcss.config.js',
},
},
},
// Compile Less to CSS
// https://github.com/webpack-contrib/less-loader
// Install dependencies before uncommenting: yarn add --dev less-loader less
// {
// test: /\.less$/,
// loader: 'less-loader',
// },
// Compile Sass to CSS
// https://github.com/webpack-contrib/sass-loader
// Install dependencies before uncommenting: yarn add --dev sass-loader node-sass
// {
// test: /\.scss$/,
// loader: 'sass-loader',
// },
],
},
// Rules for images
{
test: reImage,
oneOf: [
// Inline lightweight images into CSS
{
issuer: reStyle,
oneOf: [
// Inline lightweight SVGs as UTF-8 encoded DataUrl string
{
test: /\.svg$/,
loader: 'svg-url-loader',
options: {
name: staticAssetName,
limit: 4096, // 4kb
},
},
// Inline lightweight images as Base64 encoded DataUrl string
{
loader: 'url-loader',
options: {
name: staticAssetName,
limit: 4096, // 4kb
},
},
],
},
// Or return public URL to image resource
{
loader: 'file-loader',
options: {
name: staticAssetName,
},
},
],
},
// Convert plain text into JS module
{
test: /\.txt$/,
loader: 'raw-loader',
},
// Convert Markdown into HTML
{
test: /\.md$/,
loader: path.resolve(__dirname, './lib/markdown-loader.js'),
},
// Return public URL for all assets unless explicitly excluded
// DO NOT FORGET to update `exclude` list when you adding a new loader
{
exclude: [reScript, reStyle, reImage, /\.json$/, /\.txt$/, /\.md$/],
loader: 'file-loader',
options: {
name: staticAssetName,
},
},
// Exclude dev modules from production build
...(isDebug
? []
: [
{
test: path.resolve(
__dirname,
'../node_modules/react-deep-force-update/lib/index.js',
),
loader: 'null-loader',
},
]),
],
},
// Don't attempt to continue if there are any errors.
bail: !isDebug,
cache: isDebug,
// Specify what bundle information gets displayed
// https://webpack.js.org/configuration/stats/
stats: {
cached: isVerbose,
cachedAssets: isVerbose,
chunks: isVerbose,
chunkModules: isVerbose,
colors: true,
hash: isVerbose,
modules: isVerbose,
reasons: isDebug,
timings: true,
version: isVerbose,
},
// Choose a developer tool to enhance debugging
// https://webpack.js.org/configuration/devtool/#devtool
devtool: isDebug ? 'cheap-module-inline-source-map' : 'source-map',
};
//
// Configuration for the client-side bundle (client.js)
// -----------------------------------------------------------------------------
const clientConfig = {
...config,
name: 'client',
target: 'web',
entry: {
client: ['babel-polyfill', './src/client.js'],
},
plugins: [
// Define free variables
// https://webpack.js.org/plugins/define-plugin/
new webpack.DefinePlugin({
'process.env.NODE_ENV': isDebug ? '"development"' : '"production"',
'process.env.BROWSER': true,
__DEV__: isDebug,
}),
// Emit a file with assets paths
// https://github.com/sporto/assets-webpack-plugin#options
new AssetsPlugin({
path: path.resolve(__dirname, '../build'),
filename: 'assets.json',
prettyPrint: true,
}),
// Move modules that occur in multiple entry chunks to a new entry chunk (the commons chunk).
// https://webpack.js.org/plugins/commons-chunk-plugin/
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: module => /node_modules/.test(module.resource),
}),
...(isDebug
? []
: [
// Decrease script evaluation time
// https://github.com/webpack/webpack/blob/master/examples/scope-hoisting/README.md
new webpack.optimize.ModuleConcatenationPlugin(),
// Minimize all JavaScript output of chunks
// https://github.com/mishoo/UglifyJS2#compressor-options
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
compress: {
screw_ie8: true, // React doesn't support IE8
warnings: isVerbose,
unused: true,
dead_code: true,
},
mangle: {
screw_ie8: true,
},
output: {
comments: false,
screw_ie8: true,
},
}),
]),
// Webpack Bundle Analyzer
// https://github.com/th0r/webpack-bundle-analyzer
...(isAnalyze ? [new BundleAnalyzerPlugin()] : []),
],
// Some libraries import Node modules but don't use them in the browser.
// Tell Webpack to provide empty mocks for them so importing them works.
// https://webpack.js.org/configuration/node/
// https://github.com/webpack/node-libs-browser/tree/master/mock
node: {
fs: 'empty',
net: 'empty',
tls: 'empty',
},
};
//
// Configuration for the server-side bundle (server.js)
// -----------------------------------------------------------------------------
const serverConfig = {
...config,
name: 'server',
target: 'node',
entry: {
server: ['babel-polyfill', './src/server.js'],
},
output: {
...config.output,
path: path.resolve(__dirname, '../build'),
filename: '[name].js',
chunkFilename: 'chunks/[name].js',
libraryTarget: 'commonjs2',
},
// Webpack mutates resolve object, so clone it to avoid issues
// https://github.com/webpack/webpack/issues/4817
resolve: {
...config.resolve,
},
module: {
...config.module,
rules: overrideRules(config.module.rules, rule => {
// Override babel-preset-env configuration for Node.js
if (rule.loader === 'babel-loader') {
return {
...rule,
options: {
...rule.options,
presets: rule.options.presets.map(
preset =>
preset[0] !== 'env'
? preset
: [
'env',
{
targets: {
node: pkg.engines.node.match(/(\d+\.?)+/)[0],
},
modules: false,
useBuiltIns: false,
debug: false,
},
],
),
},
};
}
// Override paths to static assets
if (
rule.loader === 'file-loader' ||
rule.loader === 'url-loader' ||
rule.loader === 'svg-url-loader'
) {
return {
...rule,
options: {
...rule.options,
name: `public/assets/${rule.options.name}`,
publicPath: url => url.replace(/^public/, ''),
},
};
}
return rule;
}),
},
externals: [
'./assets.json',
nodeExternals({
whitelist: [reStyle, reImage],
}),
],
plugins: [
// Define free variables
// https://webpack.js.org/plugins/define-plugin/
new webpack.DefinePlugin({
'process.env.NODE_ENV': isDebug ? '"development"' : '"production"',
'process.env.BROWSER': false,
__DEV__: isDebug,
}),
// Adds a banner to the top of each generated chunk
// https://webpack.js.org/plugins/banner-plugin/
new webpack.BannerPlugin({
banner: 'require("source-map-support").install();',
raw: true,
entryOnly: false,
}),
],
// Do not replace node globals with polyfills
// https://webpack.js.org/configuration/node/
node: {
console: false,
global: false,
process: false,
Buffer: false,
__filename: false,
__dirname: false,
},
};
export default [clientConfig, serverConfig];
I have a feeling the problem lies here but I’m not sure what to do, css.cssText
is always empty:
app.get('*', async (req, res, next) => {
try {
const css = new Set();
// Global (context) variables that can be easily accessed from any React component
// https://facebook.github.io/react/docs/context.html
const context = {
// // Enables critical path CSS rendering
// // https://github.com/kriasoft/isomorphic-style-loader
insertCss: (...styles) => {
// eslint-disable-next-line no-underscore-dangle
styles.forEach(style => css.add(style._getCss()));
},
// Universal HTTP client
fetch: createFetch(fetch, {
baseUrl: config.api.serverUrl,
cookie: req.headers.cookie,
}),
};
const route = await router.resolve({
...context,
pathname: req.path,
query: req.query,
});
if (route.redirect) {
res.redirect(route.status || 302, route.redirect);
return;
}
const data = { ...route };
console.log(data);
data.children = ReactDOM.renderToString(
<App context={context}>{route.component}</App>,
);
data.styles = [{ id: 'css', cssText: [...css].join('') }];
data.scripts = [assets.vendor.js];
if (route.chunks) {
data.scripts.push(...route.chunks.map(chunk => assets[chunk].js));
}
data.scripts.push(assets.client.js);
data.app = {
apiUrl: config.api.clientUrl,
};
const html = ReactDOM.renderToStaticMarkup(<Html {...data} />);
res.status(route.status || 200);
res.send(`<!doctype html>${html}`);
} catch (err) {
next(err);
}
});
Issue Analytics
- State:
- Created 6 years ago
- Reactions:3
- Comments:7 (3 by maintainers)
Top Results From Across the Web
isomorphic-style-loader - npm
CSS style loader for Webpack optimized for critical path CSS rendering and isomoprhic web apps. Latest version: 5.3.2, last published: a ...
Read more >Render CSS on Server Side with React and Isomorphic-Style ...
Render CSS on Server Side with React and Isomorphic-Style-Loader · 1. Install the loader · 2. Make sure to use it on both...
Read more >Experts for mongoose pt - Linknovate
Name Score News
Amazon 48.2 2
Paramount Pictures 48.2 2
James Williams 48.2 2
Read more >Importing stylesheet in a server rendered react view - TypeError
Most likely that server-side rendering is not configured properly. ... appropriate styles will not loaded, since isomorphic-style-loader had ...
Read more >isomorphic-style-loader examples - CodeSandbox
Learn how to use isomorphic-style-loader by viewing and forking isomorphic-style-loader example apps on CodeSandbox.
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Probably
babel-plugin-css-modules
removes or modifies css imports inside.js
files, which is important for injecting css viawithStyles
higher order component. Try to disable this feature.@oshalygin thank you very much for crating this issue! Unfortunately, we have close it due to inactivity. Feel free to re-open it or join our Discord channel for discussion.
NOTE: The
main
branch has been updated with React Starter Kit v2, using JAM-style architecture.