webpack如何实现热替换

发布于 2022-09-06 00:01:56 字数 5729 浏览 14 评论 0

参照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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

街道布景 2022-09-13 00:01:56

要实现不刷新页面就替换更新后的内容,必须配合特定的loader实现,vue是因为有vue-loader,再结合webpack,才能判断出哪里改了

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文