Reputation: 21
I'm currently trying to use css loaders in a React/Redux Asp.Net Web Project. I started out following this example to create a shell for a project https://blog.pusher.com/how-to-use-react-with-visual-studio-and-asp-net-web-api/. I have upgraded to webpack 3.0. Here is my webpack.config.js
var path = require("path");
var webpack = require("webpack");
module.exports = {
debug: true,
devtool: "eval-source-map",
entry: {
bundle: path.join(__dirname, "src/index"),
tests: path.join(__dirname, "src/tests/all.tests.js"),
vendor: [
"jquery",
"expect"
]
},
output: {
path: path.join(__dirname, "src"),
publicPath: "/",
filename: "[name].js"
},
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})
],
module: {
rules: [
{
test: /\.js$/,
use: "babel-loader",
exclude: /node_modules/,
query: {
presets: ["es2015", "react"]
}
},
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
},
{ test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, use: "file" },
{ test: /\.(woff|woff2)$/, use: "url?prefix=font/&limit=5000" },
{ test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, use: "url?limit=10000&mimetype=application/octet-stream" },
{ test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, use: "url?limit=10000&mimetype=image/svg+xml" }
]
}
}
Here is my package.json
{
"version": "1.0.0",
"name": "ASP.NET",
"private": true,
"devDependencies": {
"babel": "6.5.2",
"babel-cli": "6.8.0",
"babel-core": "^6.26.0",
"babel-loader": "^6.2.4",
"babel-plugin-react-display-name": "2.0.0",
"babel-preset-es2015": "6.9.0",
"babel-preset-react": "6.11.1",
"babel-preset-react-hmre": "1.1.1",
"babel-register": "6.8.0",
"colors": "1.1.2",
"compression": "1.6.1",
"cross-env": "1.0.7",
"css-loader": "0.23.1",
"enzyme": "2.2.0",
"eslint": "^2.9.0",
"eslint-plugin-import": "1.6.1",
"eslint-plugin-react": "5.0.1",
"eslint-watch": "2.1.11",
"eventsource-polyfill": "0.9.6",
"expect": "1.19.0",
"express": "^4.13.4",
"extract-text-webpack-plugin": "^1.0.1",
"file-loader": "0.8.5",
"jsdom": "8.5.0",
"mocha": "^2.5.3",
"mocha-webpack": "^1.0.1",
"nock": "8.0.0",
"npm-run-all": "1.8.0",
"open": "0.0.5",
"post-loader": "^2.0.0",
"react-addons-test-utils": "15.0.2",
"redux-immutable-state-invariant": "1.2.3",
"redux-mock-store": "1.0.2",
"rimraf": "2.5.2",
"style-loader": "0.13.1",
"url-loader": "0.5.7",
"webpack": "^3.10.0",
"webpack-dev-middleware": "1.6.1",
"webpack-hot-middleware": "2.10.0"
},
"dependencies": {
"axios": "0.13.1",
"babel-plugin-webpack-loaders": "^0.9.0",
"babel-polyfill": "6.8.0",
"bootstrap": "3.3.6",
"jquery": "2.2.3",
"node-sass": "^4.7.2",
"react": "15.0.2",
"react-dom": "15.0.2",
"react-redux": "4.4.5",
"react-router": "2.4.0",
"react-router-redux": "4.0.4",
"redux": "3.5.2",
"redux-thunk": "2.0.1",
"resolve-url-loader": "^2.2.1",
"toastr": "2.1.2",
"ts-loader": "^3.4.0"
}
}
This is a sample component I have made
import React, {PropTypes} from "react";
import {Link} from "react-router";
import {connect} from "react-redux";
import * as customerActions from "../../actions/customerAction";
import "../../styles/main.css";
class CustomerPage extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
customers: []
};
}
render() {
return (
<div>
<h1>Hello World.</h1>
</div>
);
}
}
CustomerPage.propTypes = {
dispatch: PropTypes.func.isRequired,
customers: PropTypes.array.isRequired
}
function mapStateToProps(state, ownProps) {
return {
customers: state.customers
};
}
export default connect(mapStateToProps)(CustomerPage);
The css file is just an empty file I have created for a test. I have tried all three loading options mentioned at https://webpack.js.org/concepts/loaders/#using-loaders and I'm continually having this error "!!../../node_modules/css-loader/index.js!./main.css".
Here is a sample of the output in the bundle.js of this error
function(module, exports, __webpack_require__) {
// style-loader: Adds some css to the DOM by adding a <style> tag
// load the styles
var content = __webpack_require__(!(function webpackMissingModule() { var e = new Error("Cannot find module \"!!../../node_modules/css-loader/index.js!./main.css\""); e.code = 'MODULE_NOT_FOUND'; throw e; }()));
if(typeof content === 'string') content = [[module.id, content, '']];
// add the styles to the DOM
var update = __webpack_require__(588)(content, {});
if(content.locals) module.exports = content.locals;
// Hot Module Replacement
if(false) {
// When the styles change, update the <style> tags
if(!content.locals) {
module.hot.accept("!!../../node_modules/css-loader/index.js!./main.css", function() {
var newContent = require("!!../../node_modules/css-loader/index.js!./main.css");
if(typeof newContent === 'string') newContent = [[module.id, newContent, '']];
update(newContent);
});
}
// When the module is disposed, remove the <style> tags
module.hot.dispose(function() { update(); });
}
I'm currently running Node version 9.4.0 on a Windows 7 machine with Service Pack one. I'm also running this project inside of visual studio 2015. I'm assuming this is a problem with a simple fix but I have not found one yet and I've spent a few days researching this.
I managed to fix this by making some updates to the webpack config
var path = require("path");
var webpack = require("webpack");
module.exports = {
entry: {
bundle: path.join(__dirname, "./src/index"),
tests: path.join(__dirname, "src/tests/all.tests.js"),
vendor: [
"jquery",
"expect"
]
},
resolveLoader: {
moduleExtensions: ["-loader"]
},
output: {
path: path.join(__dirname, "src"),
publicPath: "/",
filename: "[name].js"
},
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
}),
new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /nb/),
new webpack.LoaderOptionsPlugin({
test: /\.css$/,
debug: true,
options: {
context: path.join(__dirname, "src"),
output: { path: path.join(__dirname, "dist") }
}
})
],
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: "babel-loader",
options: {
presets: ["es2015", "react"]
}
}
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
use: [
{ loader: "file-loader?hash=sha512&digest=hex&name=assets/[hash].[ext]" },
{ loader: "image-webpack-loader?bypassOnDebug&optimizationLevel=7&interlaced=false" }
]
},
{
test: /\.css$/,
use: [
{
loader: "style-loader"
},
{
loader: "css-loader?modules&camelCase",
options: {
modules: true
}
},
{ loader: "resolve-url-loader" }
]
},
{
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: "file-loader"
}]
},
{
test: /\.(woff|woff2)$/,
use: [
{
loader: "url?prefix=font/&limit=5000"
}
]
},
{
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: "url?limit=10000&mimetype=application/octet-stream"
}
]
}//,
//{
// test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
// use: [
// {
// loader: "url?limit=10000&mimetype=image/svg+xml"
// }
// ]
//}
]
}
}
Upvotes: 1
Views: 1551
Reputation: 21
So I did manage to solve this issue after sitting down for a few hours and fixing one error at a time. First what I didn't notice is that my bundle wasn't being updated from when I switched webpack to 3.10.0. I had a few properties in there that don't work in the new version. From there I blew away all of my node modules and reinstalled them to ensure all the dependencies were correct, I then updated my webpack config I can now import styles as a module and references the styles from the styles object.
var path = require("path");
var webpack = require("webpack");
module.exports = {
entry: {
bundle: path.join(__dirname, "./src/index"),
tests: path.join(__dirname, "src/tests/all.tests.js"),
vendor: [
"jquery",
"expect"
]
},
resolveLoader: {
moduleExtensions: ["-loader"]
},
output: {
path: path.join(__dirname, "src"),
publicPath: "/",
filename: "[name].js"
},
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
}),
new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /nb/),
new webpack.LoaderOptionsPlugin({
test: /\.css$/,
debug: true,
options: {
context: path.join(__dirname, "src"),
output: { path: path.join(__dirname, "dist") }
}
})
],
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: "babel-loader",
options: {
presets: ["es2015", "react"]
}
}
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
use: [
{ loader: "file-loader?hash=sha512&digest=hex&name=assets/[hash].[ext]" },
{ loader: "image-webpack-loader?bypassOnDebug&optimizationLevel=7&interlaced=false" }
]
},
{
test: /\.css$/,
use: [
{
loader: "style-loader"
},
{
loader: "css-loader?modules&camelCase",
options: {
modules: true
}
},
{ loader: "resolve-url-loader" }
]
},
{
test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: "file-loader"
}]
},
{
test: /\.(woff|woff2)$/,
use: [
{
loader: "url?prefix=font/&limit=5000"
}
]
},
{
test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: "url?limit=10000&mimetype=application/octet-stream"
}
]
}
]
}
}
This build seems like it will work properly, resolve-url-loader should be added which wasn't included in my previous package.json example: Here is an update with all the versions
{
"version": "1.0.0",
"name": "ASP.NET",
"private": true,
"devDependencies": {
"babel": "6.5.2",
"babel-cli": "6.8.0",
"babel-core": "^6.26.0",
"babel-loader": "^6.2.4",
"babel-plugin-react-display-name": "2.0.0",
"babel-preset-es2015": "6.9.0",
"babel-preset-react": "6.11.1",
"babel-preset-react-hmre": "1.1.1",
"babel-register": "6.8.0",
"colors": "1.1.2",
"compression": "1.6.1",
"cross-env": "1.0.7",
"css-loader": "0.23.1",
"enzyme": "2.2.0",
"eslint": "^2.9.0",
"eslint-plugin-import": "1.6.1",
"eslint-plugin-react": "5.0.1",
"eslint-watch": "2.1.11",
"eventsource-polyfill": "0.9.6",
"expect": "1.19.0",
"express": "^4.13.4",
"extract-text-webpack-plugin": "^1.0.1",
"file-loader": "0.8.5",
"jsdom": "8.5.0",
"mocha": "^2.5.3",
"mocha-webpack": "^1.0.1",
"nock": "8.0.0",
"npm-run-all": "1.8.0",
"open": "0.0.5",
"post-loader": "^2.0.0",
"react-addons-test-utils": "15.0.2",
"redux-immutable-state-invariant": "1.2.3",
"redux-mock-store": "1.0.2",
"rimraf": "2.5.2",
"style-loader": "0.13.1",
"url-loader": "0.5.7",
"webpack": "^3.10.0",
"webpack-dev-middleware": "1.6.1",
"webpack-hot-middleware": "2.10.0"
},
"dependencies": {
"axios": "0.13.1",
"babel-plugin-webpack-loaders": "^0.9.0",
"babel-polyfill": "6.8.0",
"bootstrap": "3.3.6",
"image-webpack-loader": "^4.0.0",
"jquery": "2.2.3",
"react": "15.0.2",
"react-css-modules": "^4.7.1",
"react-dom": "15.0.2",
"react-redux": "4.4.5",
"react-router": "2.4.0",
"react-router-redux": "4.0.4",
"redux": "3.5.2",
"redux-thunk": "2.0.1",
"resolve-url-loader": "^2.2.1",
"toastr": "2.1.2",
"ts-loader": "^3.4.0"
},
"scripts": {
"build": "webpack --config webpack.config.js --display-error-details",
"lint": "eslint src/tests/** src/index.js",
"start": "npm-run-all --parallel lint"
}
}
Additionally when importing a style say "import styles from ./styles/style.css" there is an issue with css loader if the styles aren't camel cased. You can add the camelCase option to the css loader but this still hasn't worked for me. Here is an example of a workaround
import React, {PropTypes} from "react";
import {Link, IndexLink} from "react-router";
import styles from "../../styles/style.css";
const Header = () => {
return (
<nav className={styles["c-sub-nav"]}>
<a href="" className={styles["c-sub-nav__item"]}>Dashboard</a>
<a href="" className={styles["c-sub-nav__item"]}>Customers</a>
<a href="" className={styles["c-sub-nav__item"]}>Reports</a>
</nav>
);
};
export default Header;
Upvotes: 1