How to build unified $templateCache when migrating AngularJS 1.x project from gulp & bower to webpack 3

1k Views Asked by At

Have a large AngularJS 1.6 project (~120 JS files), which is currently built through gulp/bower.

Looking to migrate over to using yarn & webpack, and we would prefer not to have to modify our project files just to implement webpack. Each of our AngularJS component JS files are wrapped in a IIFE, so they are already out of the global scope.

One of our gulp steps uses the gulp-angular-templatecache module, which collects all of our HTML files and neatly compacts them into a single $tmplateCache loader module.

angular.module("ourApp").run(["$templateCache", function ($templateCache) {
  $templateCache.put("/app/components/ourComponent1.html", "<div id=\"component1-html\"> ... </div>\r\n");
  $templateCache.put("/app/components/ourComponent2.html", "<div id=\"component2-html\"> ... </div>\r\n");
  // etc...
});

I have managed to figure out how to resolve most of our other build processes using webpack, but this one is giving me a problem.

I have looked at the ngtemplate-loader package, but do not think this would work for our needs because of the following:

  • Would require us to update all of our existing HTML templates to use 'require("./template.html")'
  • This would create a separate webpack module for each HTML template, which seems very inefficient.
  • Probably most important, I haven't been able to get it to work.

The current webpack configuration I have setup is based on a simple demo, and splits the project files out from the vendor files. Our project files are bundled up into a 'app.[hashcode].js' file into the /dist folder.

Ultimately, I would like to be able to inject the compiled $templateCache module, into a specific point in our final 'app.[hashcode].js' bundle file. However, right now I would be satisfied with the $templateCache definition file being created into a separate bundle file.

Is there an existing webpack plugin, or loader, or combination of plugin(s)/loader(s), that I could use to accomplish this build step? Is this even possible with webpack?

This is the base directory structure for the demo project:

/dashboard
   /app
      /assets
         /global
            global.less
         app.less
      /components
         /controllers
            dashboard.controller.js
         /directives
            yep-nope.directive.js
         /messenger
            messenger.directive.js
            messenger.html
         /services
            github-status.service.js
         dashbboard.config.js
         dashboard.module.js
      app.js
      /dist
         app.4f12bb49f144e559bd9b.js
         assets.css
         index.html
         vendor.b0a30c79aa77e0126a5c.js
   index.html
   package.json
   webpack.config.js

This is the current working webpack.config.js file:

const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
   context: __dirname,  
   entry: {
      app: path.resolve(__dirname, 'app/app.js'),
      vendor: ['angular','angular-sanitize']
   },
   output: {
      path: path.resolve(__dirname, 'dist'),
      filename: '[name].[chunkhash].js'
   },
   module: {
      rules: [
      {
         test: /\.less$/,
         use: ExtractTextPlugin.extract({
            fallback: "style-loader",
            use: ['css-loader', 'less-loader']
         })
      },
      {
         test: /\.js$/,
         loader: 'ng-annotate-loader'
      },
      {
         test: /\.html$/,
         exclude: path.resolve(__dirname, 'app/index.html'),
         use: [
            { loader: 'html-loader', options: { minimize: false } }
         ]
      }]
   },
   plugins: [
      new CleanWebpackPlugin(['dist','assets/**/*.css']),
      new HtmlWebpackPlugin({   
         title: 'GitUp',
         template: 'index.html',
         inject: 'body'
      }),
      new webpack.optimize.CommonsChunkPlugin({
         name:"vendor", filename:"[name].[chunkhash].js"
      }),
      new ExtractTextPlugin('assets.css')
   ]
};  

This is the webpack 'entry' file app/app.js:

require('./assets/app.less');

require('../node_modules/angular/angular.js');
require('../node_modules/angular-sanitize/angular-sanitize.js');

require('./components/dashboard.module.js');    // Define module
require('./components/dashboard.config.js');    // Setup config

// Load in all components files, except for files already loaded above
var reqCtx = require.context('./components', true, /^(?!.*(?:dashboard\.config|dashboard\.module)).*\.js$/);
reqCtx.keys().forEach(reqCtx);

If needed, I can provide the entire sample project...

1

There are 1 best solutions below

6
Nat Wallbank On

This may or may not be the answer you're looking for but in the past I've used html-loader to allow me to require my component template URLs, and it worked brilliantly:

https://www.npmjs.com/package/html-loader

It just inlines the template in your bundled script.