Webpack: CSS app/vendor code splitting - css

Despite many searches on the Web, I couldn't find a working example of a webpack config that allows CSS bundle splitting (app.css and vendor.css, like Ember.js does). No problem for JavaScript though. Currently I have Normalize.css as a NPM package that I would like to move to vendor.css, instead of app.css.
Here is my file :
var webpack = require('webpack');
var autoprefixer = require('autoprefixer');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: {
html: './app/index.html',
javascript: './app/app.js',
vendor: ['react', 'react-dom']
},
module: {
loaders: [
{ test: /\.html$/, loader: 'file?name=index.html' },
{ test: /\.scss$/, loader: ExtractTextPlugin.extract('style', 'css!sass!postcss') },
{ test: /\.js$/, exclude: /node_modules/, loaders: ['react-hot', 'babel?presets[]=es2015&presets[]=react'] },
{ test: require.resolve('react'), loader: 'expose?React' }
],
},
postcss: [ autoprefixer({ browsers: ['last 2 versions'] }) ],
plugins: [
new ExtractTextPlugin('app.css'),
new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.js')
],
output: {
path: './dist',
filename: 'app.js'
},
devServer: {
port: 8000
}
}
Thanks in advance !

Related

Not able to import css files in react

In App.js I wanted to import App.css file or any css file. import './App.css' is not working here and giving error " ERROR in ./src/shared/App.css 1:0
Module parse failed: Unexpected token (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders "
Directory Structure -
1. public
- bundle.js
2. src
- browser (folder) > index.js
- server (folder) > index.js
- server (folder) > App.js , App.css
This is my webpack.config.js file -
var path = require('path')
var webpack = require('webpack')
var nodeExternals = require('webpack-node-externals')
var combineLoaders = require('webpack-combine-loaders');
var browserConfig = {
entry: './src/browser/index.js',
output: {
path: path.resolve(__dirname, 'public'),
filename: 'bundle.js',
publicPath: '/'
},
module: {
rules: [
{ test: /\.(js)$/, exclude: /node_modules/, use: ['babel-loader']},
{
test: /\.css$/,
exclude: /node_modules/,
loader: combineLoaders([
{
loader: 'style-loader'
}, {
loader: 'css-loader',
query: {
modules: true,
localIdentName: '[name]__[local]___[hash:base64:5]'
}
},
])
}
]
},
resolve: {
extensions: ['*', '.js', '.jsx', '.css']
},
mode: 'production',
plugins: [
new webpack.DefinePlugin({
__isBrowser__: "true"
})
]
}
var serverConfig = {
entry: './src/server/index.js',
target: 'node',
externals: [nodeExternals()],
output: {
path: __dirname,
filename: 'server.js',
publicPath: '/'
},
mode: 'production',
module: {
rules: [
{ test: /\.(js)$/, exclude: /node_modules/, use: ['babel-loader']},
{
test: /\.css$/,
exclude: /node_modules/,
loader: combineLoaders([
{
loader: 'style-loader'
}, {
loader: 'css-loader',
query: {
modules: true,
localIdentName: '[name]__[local]___[hash:base64:5]'
}
}
])
}
]
},
resolve: {
extensions: ['*', '.js', '.jsx', '.css']
},
plugins: [
new webpack.DefinePlugin({
__isBrowser__: "false"
})
]
}
module.exports = [browserConfig, serverConfig]
To load CSS files in your ReactJS project, install the css-loader for ReactJS...
npm install --save-dev style-loader css-loader
Also, make sure to modify your webpack.config.js file, located in my project at: ./node_modules/webpack-dev-server/client/webpack.config.js. You'll need to add loaders, which will look something like...
module.exports = {
module: {
loaders: [
{ test: /\.js$/, exclude: /node_modules/, loaders: 'babel', query: { presets: ['react', 'es2015', 'stage-1'] } },
{ test: /\.css$/, loader: "style-loader!css-loader" }
]
},
...
}
Finally, make sure you have a resolution rule for CSS in webpack.config.js...
resolve: {
extensions: ['', '.js', '.css',...]
}

React-filepond external CSS is not being applied. I suspect it's a webpack issue

This is beating my head in. I'm using react-filepond module in my react app, but the external CSS is not being applied. The module works but has no style. I suspect it's a loader issue in webpack but I'm still learning webpack and probably missed something. Thanks!
Here are the imports as per react-filepond:
import { FilePond } from 'react-filepond';
import 'filepond/dist/filepond.css'; // located in node_modules
Here's my webpack.config.js.
I'm using webpack 3.12.0
const path = require('path');
const autoprefixer = require('autoprefixer');
const htmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
devtool: 'cheap-module-eval-source-map',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
chunkFilename: '[id].js',
publicPath: '/'
},
resolve: {
extensions: ['.js', 'jsx', '.css']
},
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader',
options: {
presets: ['react']
},
exclude: /node_modules/
},
{
test: /\.css$/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
importLoaders: 1,
modules: true,
localIdentName: '[name]__[local]__[hash:base64:5]'
}
},
{
loader: 'postcss-loader',
options: {
ident: 'postcss',
plugins: () => [
autoprefixer({
browsers: [
"> 1%",
"last 2 versions"
]
})
]
}
}
]
},
{
test: /\.(png|jpe?g|gif)$/,
loader: 'url-loader?limit=8000&name=images/[name].[ext]'
}
]
},
devServer: {
historyApiFallback: true
},
plugins: [
new htmlWebpackPlugin({
template: __dirname + '/src/index.html',
inject: 'body',
filename: 'index.html'
})
]
};
I found the solution for others wondering about this.
Issue: I am using CSS modules in react (note the line modules:true in the configuration of my css-loader in my webpack-config.js
The external react module I was trying to use does NOT use CSS modules.
Solution:
create a second rule for external CSS. Thus I have one for my CSS (as in the source above) and then I added this rule:
{
/* External CSS from node_modules */
test: /\.css$/,
include: /node_modules/,
loader: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
minimize: true,
},
}
]
},
Most importantly, I did NOT turn on CSS Modules
And then, in my other CSS rule, I added:
exclude: /node_modules/,

PostCSS & Webpack configuration

I'm really disheartened, because I can't find any useful resource on the subject.
I merely want to watch my .css files, use post css' plugins to transform them and finally export them to my /public folder as I already do with my .jsx files
Here's my web pack configuration
const path = require('path');
const webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: path.resolve('src/index.jsx'),
output: {
path: path.resolve('public'),
filename: 'bundle.js'
},
resolve: {
extensions: ['*', '.js', '.jsx']
},
devServer: {
publicPath: "/",
contentBase: "./public"
},
module: {
rules: [
{
test: /\.css$/,
exclude: /node_modules/,
loader: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: [
{
loader: 'css-loader',
options: {
modules: true,
localIdentName: '[name]__[local]___[hash:base64:5]'
}
}, {
loader: 'postcss-loader',
options: {
plugins: function() {
return [require('lost'), require('postcss-cssnext'), require('postcss-import')]
}
}
}
]
})
}, {
test: /\.jsx?$/,
use: [
{
loader: 'babel-loader',
options: {
presets: ['es2015', 'react']
}
}
],
exclude: /(node_modules|bower_components)/
}
]
},
plugins: [new ExtractTextPlugin("main.css")]
}
I assume you are using webpack2
If you want your css file dumped out separately, you would need ExtractTextPlugin. Here is my css loader which works
I define the post css plugins right within the webpack config, because then it stays in one place. Hope this helps:
var ExtractTextPlugin = require('extract-text-webpack-plugin');
...
...
module.exports = {
...
...
module: {
rules: [
...
...
{
test: /\.css$/,
exclude: /node_modules/,
loader: ExtractTextPlugin.extract(
{ fallback: 'style-loader',
use: [{
loader: 'css-loader',
options: {
modules: true,
localIdentName:'[name]__[local]___[hash:base64:5]'
}
},
{
loader: 'postcss-loader',
options: {
plugins: function() {
return [
require('autoprefixer')
]
}
}
},
]
})
},
}
Maybe your plugins are incorrectly created.
Try
return [require('lost')(), require('postcss-cssnext')(), require('postcss-import')()]
(Note the () to invoke the plugin creation).
Also are you actually using import/require() to include your css? If not you should, no magic stuff will glob your css :)

CSS file don't not create with webpack

I use webpack and i would like generate my CSS file with SASS.
So i've add css-loader and sass-loader. But, webpack don't create my CSS folder. My webpackconfig :
const webpack = require('webpack'),
ExtractTextPlugin = require('extract-text-webpack-plugin'),
BrowserSyncPlugin = require('browser-sync-webpack-plugin');
module.exports = {
entry: './js/app.js',
output: {
path: './public',
filename: 'app.bundle.js'
},
module: {
loaders: [
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['es2015', 'stage-2']
}
},
{
test: /\.scss$/,
loaders: ExtractTextPlugin.extract(["style", "css", "sass"])
}
]
},
plugins: [
new ExtractTextPlugin('app.bundle.css'),
new BrowserSyncPlugin(
{
host: 'localhost',
port: 3000,
server: { baseDir: ['./'] }
}
)
]
}
Do you have any idea ?
Thank you !
You could use the style!css!sass loaders. Just install them using npm and set the config below in your webpack.config.
{
test: /\.scss$/,
loader: 'style!css!sass?sourceMap'
}
Your final webpack.config should look like this:
const webpack = require('webpack'),
ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: './js/app.js',
output: {
path: './js',
filename: 'app.bundle.js'
},
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['es2015', 'stage-2']
}
},
{
test: /\.scss$/,
loader: 'style!css!sass?sourceMap'
}
]
},
plugins: [
new webpack.HotModuleReplacementPlugin()
]
}
Now your CSS should be bundled properly.
plugins should be a root property, not a property of module.
const webpack = require('webpack'),
ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: './js/app.js',
output: {
path: './js',
filename: 'app.bundle.js'
},
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel',
query: {
presets: ['es2015', 'stage-2']
}
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract('style', 'css!sass')
}
]
},
plugins: [
new ExtractTextPlugin('app.bundle.css')
]
}
You have to import the scss file somewhere, like your index.js or App.js:
e.g. import './sass/main.scss';

Importing vendor css when using webpack + css components

I'm trying to use things like font-awesome and foundation with React and css modules but I can't figure it out how to import them into my project properly.
Note that I'm using HotModuleReplacementPlugin and ExtractTextPlugin to get a single css file.
Somewhere in the top-level component's css file I'd like to be able to just do #import 'font-awesome'; but how can I do it so that the file will be treated as-is and the classes won't end up localised to font_awesome__fa-check and such?
This is my webpack config:
var paths = {
app: path.join(__dirname, './app/'),
dist: path.join(__dirname, './dist/'),
external: path.join(__dirname, './node_modules/'),
}
module.exports = {
entry: {
site: [
'webpack-dev-server/client?http://localhost:5000',
'webpack/hot/dev-server',
path.join(paths.app, '/index.js'),
]
},
output: {
path: paths.dist,
publicPath: '/',
filename: 'scripts/[name].[hash].js',
chunkFilename: '[name].[chunkhash].js'
},
resolve: {
extensions: ['', '.js'],
root: paths.app,
alias: {
'font-awesome.css': path.join(paths.external, '/font-awesome/css/font-awesome.min.css')
}
},
module: {
loaders: [
{
test: /\.jsx?$/,
loaders: ['babel'],
include: path.join(__dirname, 'app')
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract('style-loader', 'css-loader?modules&localIdentName=[name]__[local]&importLoaders=1', 'postcss-loader')
}
]
},
postcss: [
require('autoprefixer-core'),
],
devtool: 'inline-source-map',
plugins: [
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
new ExtractTextPlugin("styles/[name].[chunkhash].css", {allChunks: true}),
new HtmlWebpackPlugin({
template: path.join(paths.app, '/site.html'),
filename: 'index.html',
inject: 'body',
chunks: ['site']
}),
]
};
Thanks.
You could leverage include / exclude option when configuring loaders.
E.g. given that all of your custom css is somewhere in the /app/ directory, while foundation and font-awesome are not.
...
module: {
loaders: [
{
test: /\.css$/,
loader: ExtractTextPlugin.extract('style-loader', 'css-loader?modules&localIdentName=[name]__[local]&importLoaders=1', 'postcss-loader'),
include: path.join(__dirname, 'app')
},
{
test: /\.css$/,
loader: ExtractTextPlugin.extract('style-loader!css-loader'),
exclude: path.join(__dirname, 'app')
}
]
},
Another option is to use different extension for the files that use css-modules syntax. You could use .mcss.
...
module: {
loaders: [
{
test: /\.mcss$/,
loader: 'css-loader?modules&localIdentName=[name]__[local]&importLoaders=1'
},
{
test: /\.css$/,
loader: 'css-loader')
}
],
postLoaders: [
{
test: /\.(css|mcss)$/,
loader: ExtractTextPlugin.extract('style-loader')
}
]
},

Resources