vitaliy-bobrov / angular-hot-loader

🔥 Webpack Hot Module Replacement for Angular 1.x applications.
32 stars 7 forks source link

Doesn't Work with templates #16

Open AhmedAymanM opened 7 years ago

AhmedAymanM commented 7 years ago

I'm unable to make HMR to work with template, I'm not sure if it's a bug or it have something to do with my setup.

vitaliy-bobrov commented 7 years ago

@AhmedAymanM , it'll be helpfull to share your configuration

AhmedAymanM commented 7 years ago

@vitaliy-bobrov here is code where I'm getting the issue https://github.com/AhmedAymanM/angularjs-webpack

and that's my webpack configuration:

var webpack = require('webpack');
var autoprefixer = require('autoprefixer');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var CopyWebpackPlugin = require('copy-webpack-plugin');
var ImageminPlugin = require('imagemin-webpack-plugin').default;
var ngAnnotatePlugin = require('ng-annotate-webpack-plugin');

var ENV = process.env.npm_lifecycle_event;
var isTest = ENV === 'test' || ENV === 'test-watch';
var isProd = ENV === 'build';

module.exports = function makeWebpackConfig() {
  var config = {};
  config.entry = isTest ? void 0 : {
    app: './src/index.js',
    vendor: ['angular','@uirouter/angularjs']
  };
  config.output = isTest ? {} : {
    path: __dirname + '/dist',
    publicPath: isProd ? '/' : 'http://localhost:8080/',
    filename: isProd ? '[name].[hash].js' : '[name].bundle.js',
    chunkFilename: isProd ? '[name].[hash].js' : '[name].bundle.js'
  };

  if (isTest) {
    config.devtool = 'inline-source-map';
  }
  else if (isProd) {
    config.devtool = 'source-map';
  }
  else {
    config.devtool = 'eval-source-map';
  }
  config.module = {
    rules: [{
      test: /\.js$/,
      use:  [
              'angular-hot-loader',
              'babel-loader'
            ],
      exclude: /node_modules/
    }, {
      use: isTest ? 'null-loader' : ExtractTextPlugin.extract({
        fallback: 'style-loader',
        use: [{
            loader: 'css-loader',
            query: {
              sourceMap: true
            }
          },
          {
            loader: 'postcss-loader',
            query: {
              sourceMap: true
            }
          },
          {
            loader: 'sass-loader'
          }]
      })
    }, {
      test: /\.(png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot)$/,
      use: 'file-loader'
    }, {
      test: /\.html$/,
      use: 'raw-loader'
    }]
  };

  if (isTest) {
    config.module.rules.push({
      enforce: 'pre',
      test: /\.js$/,
      exclude: [
        /node_modules/,
        /\.spec\.js$/
      ],
      use: [
        {
          loader: 'istanbul-instrumenter-loader',
          options: {
            esModules: true
          }
        }
      ]
    })
  }
  config.plugins = [

    new webpack.NamedModulesPlugin(),

    new ngAnnotatePlugin({
        add: true,
    }),

    new webpack.LoaderOptionsPlugin({
      test: /\.scss$/i,
      options: {
        postcss: {
          plugins: [autoprefixer]
        }
      }
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: "vendor",
      filename: "vendor.bundle.js"
    })
  ];

  if (!isTest) {

    config.plugins.push(
      new HtmlWebpackPlugin({
        template: './src/index.html',
        inject: 'body'
      }),

      new ExtractTextPlugin({filename: 'css/[name].css', disable: !isProd, allChunks: true})
    )
  }

  if (isProd) {
    config.plugins.push(

      new ImageminPlugin({ test: /\.(jpe?g|png|gif|svg)$/i }),

      new webpack.NoEmitOnErrorsPlugin(),

      new webpack.optimize.UglifyJsPlugin(),

      new CopyWebpackPlugin([{
        from: __dirname + '/src/assets'
      }])
    )
  }

  config.devServer = {
    contentBase: './src/assets',
    stats: 'minimal',
    publicPath: '/'
  };

  return config;
}();
rodrigosaling commented 7 years ago

I am having a similar problem, and I have to reload the page to display the changes in template. I have a main.js that bootstraps Angular to the page, loading AppModule that imports an AppComponent that has an import templateUrl from './app.html';. If I change the app.html, the hot-reloader detects it and prints this info:

image

But does not reload the HTML on the browser.

If instead of using the templateUrl of the component, I declare the HTML directly with template, then it works. So I guess is something related to the import of a HTML file. I am using file-loader on Webpack to load template files. Maybe I should use html-loader?

Update 1: with html-loader the template doesn't even load on the browser.

Update 2: so I made it work using template: require('./app.html'), on the component and html-loader for HTML files. Only time will tell if any of these solutions work with versioned images references in the middle of the code.

Update 3: I am using Webpack 2.5.1, dev-middleware 1.10.1, hot-middleware 2.17.1 and angular-hot-loader 0.9.3

vitaliy-bobrov commented 7 years ago

@rodrigosaling, templateUrl hasn't implemented yet.

zalishchuk commented 7 years ago

@rodrigosaling if webpack is used to bundle your angular application, you should include your templates directly in your bundle, so you can reduce a large amount of requests to your server caused by templateUrl option.

rodrigosaling commented 7 years ago

Hi @zalishchuk ! Thanks for the tip, but I was trying to use templateUrl because I already use this property today on my current project, but using Grunt with grunt-html2js (that gets all HTML references and concatenate them in one file of ng-templates). So I was just trying to copy the way I currently work.