Friday, 26 May 2017

Getting webpack to work with hot module reload

Been playing with this for the past 10 hours or so trying to get it to work, tried all combinations of every github/so issue/question/answer I could find.

I have my actual Vue application on www.example.com/test/v4/test2/ (port 80) and trying to load the bundle.js output by the webpack dev server on port 9999, included with a script src tag from www.example.com:9999/bundle.js.

Surprisingly, it works by loading the script from www.example.com:9999/bundle.js and not www.example.com:9999/build/bundle.js. Guess that configuration option does nothing, it's just a trap to make people kill their computers.

My webpack.config.js:

module.exports = {
  devServer: {
    headers: {
        'Access-Control-Allow-Origin': '*'
    },
    port: 9999,
    host: '0.0.0.0',
    public: 'www.example.com:9999',
    publicPath: 'http://www.example.com:9999/?abc',
    hot: true,
    inline: true,
    contentBase: './build/'
//    contentBase: 'http://www.example.com/test/v4/test2/'
  },
  entry: {
     src: [ __dirname + '/src/site/js/src.js', 'webpack-dev-server/client']
  },
  devtool: 'source-map',
  output: {
    // This is where images AND js will go
    path: __dirname + '/build',
    // This is used to generate URLs to e.g. images
    publicPath: 'http://www.example.com:9999/build/',
    filename: PROD ? '[name].min.js' : '[name].js'
  },
  module: {
    loaders: [

      { test: /\.vue$/, loader: 'vue-loader' },

      { test: /\.less$/, loader: 'style-loader!css-loader!less-loader' }, // use ! to chain loaders
      { test: /\.css$/, loader: 'style-loader!css-loader' },
      { test: /\.coffee$/, loader: 'coffee-loader' },

      { test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192' }, // inline base64 URLs for <=8k images, direct URLs for the rest

      { test: /\.js$/, exclude: /(node_modules|bower_components)/, use: [ {loader: 'babel-loader', query: { presets: ['es2015'] } }, { loader: 'vue-hot-reload-loader' }]},

      { test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/font-woff'},
      { test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=application/octet-stream'},
      { test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: 'file'},
      { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: 'url?limit=10000&mimetype=image/svg+xml'}
    ]
  },
  plugins: [
//    new webpack.HotModuleReplacementPlugin(),
//    new webpack.NoEmitOnErrorsPlugin(),
    new webpack.NamedModulesPlugin(),
    new webpack.ProvidePlugin({
        "_": "underscore",
        "$": "jquery",
        "jquery": "jquery",
        "jQuery": "jquery",
        "moment": "moment",
        "vue" : "vue/dist/vue",
        "vuex" : "vuex/dist/vuex"
    })
  ].concat( PROD?[ new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } }) ]:[] )
};

My package.json:

...
  "dependencies": {
    "bootstrap": "^3.3.5",
    "jquery": "^2.2.4",
    "moment": "^2.18.1",
    "slick-carousel": "^1.6.0",
    "socketcluster-client": "^5.3.1",
    "underscore": "^1.8.3",
    "v-tooltip": "^2.0.0-beta.4",
    "vue": "^2.3.3",
    "vue-progressbar": "^0.7.2",
    "vue-resource": "^1.3.3",
    "vue-router": "^2.5.3",
    "vuex": "^2.3.1"
  },
  "devDependencies": {
    "babel": "^6.23.0",
    "babel-core": "^6.24.1",
    "babel-loader": "^7.0.0",
    "babel-preset-es2015": "^6.24.1",
    "bootstrap-webpack": "0.0.6",
    "coffee-loader": "^0.7.3",
    "coffee-script": "^1.12.6",
    "css-loader": "^0.28.3",
    "exports-loader": "^0.6.4",
    "expose-loader": "^0.7.3",
    "extract-text-webpack-plugin": "^2.1.0",
    "file-loader": "^0.11.1",
    "imports-loader": "^0.7.1",
    "less": "^2.7.2",
    "less-loader": "^4.0.3",
    "script-loader": "^0.7.0",
    "style-loader": "^0.18.1",
    "url-loader": "^0.5.8",
    "vue-hot-reload-loader": "^0.1.3",
    "vue-loader": "^12.1.0",
    "vueify": "^9.4.1",
    "webpack": "^2.6.1",
    "webpack-dev-middleware": "^1.10.2",
    "webpack-dev-server": "^2.4.5",
    "webpack-hot-middleware": "^2.18.0"
  },
...

I could not get it to "work" until 10 hours later when I discovered that if I keep the dev server running in one terminal:

node_modules/.bin/webpack-dev-server --hot --inline

... and in another

webpack --watch 

... and browsing to:

http://www.example.com:9999/webpack-dev-server//www.example.com/test/v4/test2/

the double slash after webpack-dev-server is not a typo, anything else won't work but this works regardless of what I put in the webpack.config

.. although it still does not work "as expected", basically it does not reload the code, it does not refresh the page, but if I refresh the page manually it works (running either on its own does not even if reloading manually). I do see the log messages in the browser console when making changes to the code though, but nothing else happens:

(2) [WDS] App updated. Recompiling...
[WDS] App hot update...

So I guess, leaving aside the brain-mashing configuration options as some sort of practical joke, my question is: am I wrong to expect it to reload the code automatically, without page reloads? Because that's what the webpack HMR docs (sic) advertise: reloading the code while preserving the state of the application.



via Nick M

No comments:

Post a Comment