I have a React and Redux project using Webpack to build, and am trying to build for production for the first time. I built off of this project skeleton for my project. In my index.ejs
file (the template webpack uses to build off of), I have this line:
<link rel="stylesheet" type="text/css" href="/vendor/ui-toolkit/css/nm/main.min.css" media="all">
After running npm run build
and running the resulting index.html
output, I get this error in the console:
Failed to load resource: the server responded with a status of 404 (Not Found) http://localhost:3000/vendor/ui-toolkit/css/nm/main.min.css
How do I include this stylesheet (and the fonts that are in that same folder) into the build? Here is the code:
In package.json
, you can see there is a npm run build
script, which is what I run to generate my production dist
folder.
package.json:
{
"engines": {
"npm": ">=3"
},
"scripts": {
"open:src": "babel-node tools/srcServer.js",
"open:dist": "babel-node tools/distServer.js",
"clean-dist": "npm run remove-dist && mkdir dist",
"remove-dist": "rimraf ./dist",
"prebuild": "npm run clean-dist",
"build": "babel-node tools/build.js && npm run open:dist"
},
"dependencies": {
"babel-eslint": "7.0.0",
"object-assign": "4.1.0",
"react": "15.2.0",
"react-dom": "15.2.0",
"react-redux": "4.4.5",
"react-router": "2.8.1",
"react-router-redux": "4.0.6",
"redux": "3.5.2",
"redux-thunk": "2.1.0",
"babel-polyfill": "6.13.0"
},
"devDependencies": {
"babel-cli": "6.10.1",
"babel-core": "6.10.4",
"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-preset-stage-1": "6.5.0",
"babel-register": "6.9.0",
"browser-sync": "2.13.0",
"chalk": "1.1.3",
"coveralls": "2.11.11",
"cross-env": "1.0.8",
"css-loader": "0.23.1",
"extract-text-webpack-plugin": "1.0.1",
"file-loader": "0.9.0",
"html-webpack-plugin": "2.22.0",
"less": "2.7.1",
"less-loader": "2.2.3",
"node-sass": "3.8.0",
"npm-run-all": "2.3.0",
"open": "0.0.5",
"prompt": "1.0.0",
"replace": "0.3.0",
"rimraf": "2.5.3",
"sass-loader": "4.0.0",
"style-loader": "0.13.1",
"url-loader": "0.5.7",
"webpack": "1.13.1",
"webpack-dev-middleware": "1.6.1",
"webpack-hot-middleware": "2.12.1",
"webpack-md5-hash": "0.0.5"
}
}
The "build":
npm script runs babel-node tools/build.js
, which looks like this:
build.js:
import webpack from 'webpack';
import config from '../webpack.config.prod';
import {chalkError, chalkSuccess, chalkWarning, chalkProcessing} from './chalkConfig';
process.env.NODE_ENV = 'production'; // this assures React is built in prod mode and that the Babel dev config doesn't apply.
webpack(config).run((error, stats) => {
if (error) { // so a fatal error occurred. Stop here.
console.log(chalkError(error));
return 1;
}
const jsonStats = stats.toJson();
if (jsonStats.hasErrors) {
return jsonStats.errors.map(error => console.log(chalkError(error)));
}
if (jsonStats.hasWarnings) {
console.log(chalkWarning('Webpack generated the following warnings: '));
jsonStats.warnings.map(warning => console.log(chalkWarning(warning)));
}
// if we got this far, the build succeeded.
console.log(chalkSuccess('Your app is compiled in production mode in /dist. It\'s ready to roll!'));
return 0;
});
Next, you can see that webpack's config is being imported from
../webpack.config.prod` - here is that file:
webpack.config.prod.js:
import webpack from 'webpack';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
import WebpackMd5Hash from 'webpack-md5-hash';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import autoprefixer from 'autoprefixer';
import path from 'path';
const GLOBALS = {
'process.env.NODE_ENV': JSON.stringify('production'),
__DEV__: false
};
export default {
resolve: {
extensions: ['', '.js', '.jsx']
},
debug: true,
devtool: 'source-map', // more info:https://webpack.github.io/docs/build-performance.html#sourcemaps and https://webpack.github.io/docs/configuration.html#devtool
noInfo: true, // set to false to see a list of every file being bundled.
entry: path.resolve(__dirname, 'src/index'),
target: 'web', // necessary per https://webpack.github.io/docs/testing.html#compile-and-test
output: {
path: path.resolve(__dirname, 'dist'),
publicPath: '/',
filename: '[name].[chunkhash].js'
},
plugins: [
// Hash the files using MD5 so that their names change when the content changes.
new WebpackMd5Hash(),
// Optimize the order that items are bundled. This assures the hash is deterministic.
new webpack.optimize.OccurenceOrderPlugin(),
// Tells React to build in prod mode. https://facebook.github.io/react/downloads.html
new webpack.DefinePlugin(GLOBALS),
// Generate an external css file with a hash in the filename
new ExtractTextPlugin('[name].[contenthash].css'),
// Generate HTML file that contains references to generated bundles. See here for how this works: https://github.com/ampedandwired/html-webpack-plugin#basic-usage
new HtmlWebpackPlugin({
template: 'src/index.ejs',
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true
},
inject: true,
// Note that you can add custom options here if you need to handle other custom logic in index.html
// To track JavaScript errors via TrackJS, sign up for a free trial at TrackJS.com and enter your token below.
trackJSToken: ''
}),
// Eliminate duplicate packages when generating bundle
new webpack.optimize.DedupePlugin(),
// Minify JS
new webpack.optimize.UglifyJsPlugin()
],
module: {
loaders: [
{test: /\.jsx?$/, exclude: /node_modules/, loader: 'babel'},
{test: /\.eot(\?v=\d+.\d+.\d+)?$/, loader: 'url?name=[name].[ext]'},
{test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url?limit=10000&mimetype=application/font-woff&name=[name].[ext]"},
{test: /\.ttf(\?v=\d+.\d+.\d+)?$/, loader: 'url?limit=10000&mimetype=application/octet-stream&name=[name].[ext]'},
{test: /\.svg(\?v=\d+.\d+.\d+)?$/, loader: 'url?limit=10000&mimetype=image/svg+xml&name=[name].[ext]'},
{test: /\.(jpe?g|png|gif)$/i, loader: 'file?name=[name].[ext]'},
{test: /\.ico$/, loader: 'file?name=[name].[ext]'},
{test: /(\.css|\.scss)$/, loader: ExtractTextPlugin.extract('css?sourceMap!postcss!sass?sourceMap')}
]
},
postcss: ()=> [autoprefixer]
};
Any ideas why it can't find my stylesheet? How do I include it into the webpack build and link to it?
You do not need modify your index.ejs file. Leave it as default. Then in your main
index.js
file, just import thecss
. Webpack will compile that.