Reputation: 18097
I've been reading and following tutorials, but I am stuck. I was able to accomplish things listed in tutorials but not combine them together.
I want to write a configuration file that would do these things:
So Compile/Transpile Files, Live/Hot Reload, Hash Filenames, minify, and sourcemaps.
Right now I am thinking of abandoning Webpack, and only use it for transpiling and do everything in Gulpjs.
The stuff in bold is where I had a lot of trouble as well. Existing Solutions include generating JSON file, and reading them per request (inefficent!), generating full html file and injecting them (breaks many flows plus cant modify script tag with special attributes if needed, they get written over).
Upvotes: 0
Views: 283
Reputation: 4749
THERE IS NO ONE FITS FOR ALL!
Many configs aren't necessarily bound to webpack, they can be found in scripts
entry of package.json
, or just reside in presets
of .babelrc
. Of course, you can configure everything about ES6 just in webpack, but you can also ONLY put them in package.json, so it's more a flavour/ team convention thing. To make it simple, i would just share one workable solution:
loaders
for Sass/Scss, JSX/ES6 Transformationexports.module = {
rules: [
{
test: /\.scss$/,
use: isProd
? ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader', 'sass-loader']
})
: ['style-loader', 'css-loader', 'sass-loader']
},
{
test: /\.js|jsx$/,
use: 'babel-loader',
exclude: /node_modules/
}
]
}
if (isProd) {
module.exports.plugins = (module.exports.plugins || []).concat([
new ExtractTextPlugin({
filename: '[name].[contenthash].css'
})
})
}
ExtractTextPlugin
are used here as you may don't want inline
css in production, but i will still use them in development.
HotModuleReplacement
and react-hot-loader
plugins for Code Hot ReloadingEven better than Auto Refresh/Reload
a page, it will only reload the changed parts of your app (think about Ajax), this helps to iterate even faster and more importantly, it helps you to retain the state of your app, which is fairly important for large scale SPA where state management
, time travel debugging
etc can be useful.
if (isDev) {
module.exports.entry.app = [
'webpack-hot-middleware/client',
'react-hot-loader/patch'
].concat(module.exports.entry.app)
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.HotModuleReplacementPlugin()
])
}
As you don't want webpack-dev-server, give webpack-dev-middleware and webpack-hot-middleware a shot, and they will be used in your server.js
in development:
// compile your bundle.js on the fly (in memory serve)
app.use(require("webpack-dev-middleware")(compiler, {
noInfo: true,
publicPath: "/"
}))
// notify the browser client updated bundle is ready
app.use(require("webpack-hot-middleware")(compiler))
Code Splitting
and HtmlWebpackPlugin
to hash filenames and auto update the referred urls.if (isProd) {
module.exports.output = Object.assign({}, module.exports.output, {
filename: '[name].[chunkhash].js',
chunkFilename: '[id].[chunkhash].js'
})
module.exports.plugins = (module.exports.plugins || []).concat([
new HtmlWebpackPlugin({
template: 'index.ejs',
inject: true,
chunksSortMode: 'dependency'
})
})
}
To remove old hashed files, just simple script in package.json
"scripts": {
"build": "rm -rf public/** && NODE_ENV=production webpack --progress --hide-modules"
}
UglifyJsPlugin
, LoaderOptionsPlugin
plugins for Minifying and generating source Mapsif (isProd) {
module.exports.devtool = '#source-map'
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
},
sourceMap: true
}),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.LoaderOptionsPlugin({
minimize: true,
debug: false
})
])
} else {
module.exports.devtool = '#eval-source-map'
}
A "sum up" webpack.config.js
may look like this:
const path = require('path')
const resolve = p => path.resolve(__dirname, p)
const webpack = require('webpack')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const isProd = process.env.NODE_ENV === 'production'
module.exports = {
entry: {
app: [
resolve('src/js/main.js')
]
},
output: {
path: resolve('public'),
filename: 'bundle.js'
},
module: {
rules: [
{
test: /\.scss$/,
use: isProd
? ExtractTextPlugin.extract({
fallback: 'style-loader',
use: ['css-loader', 'sass-loader']
})
: ['style-loader', 'css-loader', 'sass-loader']
},
{
test: /\.js|jsx$/,
use: 'babel-loader',
exclude: /node_modules/
}
]
}
}
if (isProd) {
module.exports.devtool = '#source-map'
module.exports.output = Object.assign({}, module.exports.output, {
filename: '[name].[chunkhash].js',
chunkFilename: '[id].[chunkhash].js'
})
module.exports.plugins = (module.exports.plugins || []).concat([
new ExtractTextPlugin({
filename: '[name].[contenthash].css'
}),
new HtmlWebpackPlugin({
template: 'index.ejs',
inject: true,
chunksSortMode: 'dependency'
}),
new webpack.optimize.UglifyJsPlugin({
compress: {
warnings: false
},
sourceMap: true
}),
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.LoaderOptionsPlugin({
minimize: true,
debug: false
})
])
} else {
module.exports.entry.app = [
'webpack-hot-middleware/client',
'react-hot-loader/patch'
].concat(module.exports.entry.app)
module.exports.devtool = '#eval-source-map'
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.HotModuleReplacementPlugin()
])
}
It's only for reference, happy tweaking!
In case you want a quick demo: https://github.com/lxynox/so-example-webpack
Upvotes: 2
Reputation: 9034
Upvotes: 0