webpack如何实现热替换
参照vue-cli建立的项目中有关开发模式的webpack配置,基本的代码和其配置基本一样,但是vue的可以实现热替换,就是内容改了后不用刷新页面内容也会改变,而我写的配置只能实现热重载,也就是更改内容后自动刷新,下面是配置
webpack.base.conf.js
var path = require('path');
var config = require('../config');
var webpack = require('webpack');
var utils = require('./utils');
function resolve(dir) {
return path.join(__dirname, '..', dir);
}
module.exports = {
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.json'],
alias: {
'components': path.join(__dirname, '../src/components'),
'common': path.join(__dirname, '../src/comon')
}
},
module: {
rules: [{
test: /\.js$/,
loader: 'eslint-loader',
enforce: 'pre',
include: resolve('src'),
options: {
formatter: require("eslint-friendly-formatter")
}
}, {
test: /\.js$/,
loader: 'babel-loader',
include: resolve('src'),
options: {
presets: ['env'],
plugins: ['transform-runtime'],
cacheDirectory: true
}
}, {
test: /\.ejs$/,
loader: 'ejs-loader',
}, {
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('images/[name].[hash:7].[ext]')
}
}, {
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}]
},
externals: {
jquery: 'jQuery'
}
}
webpack.dev.conf.js
var webpack = require('webpack');
var baseWebpackConfig = require('./webpack.base.conf');
var config = require('../config');
var merge = require('webpack-merge');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin');
Object.keys(baseWebpackConfig.entry).forEach(function (name) {
baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]);
})
module.exports = merge(baseWebpackConfig, {
module: {
rules: [{
test: /\.scss$/,
use: [{
loader: 'style-loader'
}, {
loader: 'css-loader',
options: {
minimize:true,
sourceMap: config.dev.cssSourceMap
}
}, {
loader: 'postcss-loader',
options: {
sourceMap: config.dev.cssSourceMap,
plugins: function () {
return [
require('autoprefixer')()
];
}
}
}, {
loader: 'sass-loader',
options: {
sourceMap: config.dev.cssSourceMap
}
}],
}]
},
devtool: '#cheap-module-eval-source-map',
plugins: [
new webpack.DefinePlugin({
'process.env': JSON.stringify(config.dev.env.NODE_ENV)
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
}),
new FriendlyErrorsPlugin()
]
})
dev-client.js
require('eventsource-polyfill')
var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
hotClient.subscribe(function (event) {
if (event.action === 'reload') {
window.location.reload()
}
})
dev-server.js
var config = require('../config');
process.env.NODE_ENV = config.dev.env.NODE_ENV;
var opn = require('opn');
var path = require('path');
var express = require('express');
var webpack = require('webpack');
var proxyMiddleware = require('http-proxy-middleware');
var webpackConfig = require('./webpack.dev.conf');
var port = process.env.port || config.dev.port;
var autoOpenBrowser = !!config.dev.autoOpenBrowser;
var proxyTable = config.dev.proxyTable;
var app = express();
var compiler = webpack(webpackConfig);
var devMiddleware = require('webpack-dev-middleware')(compiler, {
publicPath: webpackConfig.output.publicPath,
quiet: true,
// stats: {
// color: true
// }
});
var hotMiddleware = require('webpack-hot-middleware')(compiler, {
log: () => {}
});
// force page reload when html-webpack-plugin template changes
compiler.plugin('compilation', function (compilation) {
compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
hotMiddleware.publish({
action: 'reload'
});
cb();
})
})
Object.keys(proxyTable).forEach(function (content) {
var options = proxyTable[content];
if (typeof options === 'string') {
options = {
target: options
}
}
app.use(proxyMiddleware(options.filter || content, options))
})
app.use(require('connect-history-api-fallback')());
app.use(devMiddleware);
app.use(hotMiddleware);
// serve pure static assets
var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
app.use(staticPath, express.static('./static'))
var uri = 'http://localhost:' + port;
var _resolve;
var readyPromise = new Promise(resolve => {
_resolve = resolve
});
console.log('> Starting dev server...')
devMiddleware.waitUntilValid(function () {
console.log('> Listening at ' + uri + '\n');
if (autoOpenBrowser) {
opn(uri);
}
_resolve();
})
var server = app.listen(port);
module.exports = {
ready: readyPromise,
close: () => {
server.close()
}
}
其中HotModuleReplacementPlugin这个插件就是用来配置热替换的,这个我也配置上去了,但是还是不行,不知道是不是还漏了什么步骤,和vue项目的配置主要区别就是少了针对vue文件处理,其他内容基本都是一样的,不知道问题是否出现在这个上?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
要实现不刷新页面就替换更新后的内容,必须配合特定的loader实现,vue是因为有vue-loader,再结合webpack,才能判断出哪里改了