【问题标题】:AngularJS + webpack how to hash template htmlsAngularJS + webpack如何散列模板html
【发布时间】:2019-08-21 23:53:38
【问题描述】:

在使用 gulp 之前,我已经迁移了我们的 AngularJS 应用程序以使用 webpack。在 gulp 版本中,我使用 rev 插件来修改所有文件(css、js 和 html),但是在 webpack 模式下,我找不到将哈希添加到 html 模板的方法 - 这会导致浏览器提供旧 html 文件时出现问题.如何修复?以下是 webpack conf 文件

const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const OpenBrowserPlugin = require('open-browser-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

const RemoteServer = process.env.REMOTE_SERVER;
const appEnv = process.env.NODE_ENV || 'development';
const isProduction = appEnv === 'production';

const patterns = require('../server/src/main/resources/regex.json');

const appPath = path.join(__dirname, 'app');
const buildPath = path.join(__dirname, 'artifacts');

const config = {
    entry: [path.join(appPath, 'index.js')],

    output: {
        path: buildPath,
        filename: '[name].[hash].js',
        chunkFilename: '[name].[hash].js'
    },

resolve: {
    modules: ['node_modules', appPath],
    alias: {
        'ui-select-css': path.resolve('./node_modules/ui-select/dist/select.css'),
        fonts: path.resolve(__dirname, 'assets/fonts')
    }
},

module: {
    rules: [
        {
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'eslint-loader',
            options: {
                emitWarning: true,
                quiet: true
            }
        },
        {
            test: /\.js$/,
            loader: 'babel-loader',
            exclude: /node_modules/
        },
        {
            test: /\.css$/,
            use: [
                MiniCssExtractPlugin.loader,
                'css-loader',
                'resolve-url-loader'
            ]
        },
        {
            test: /\.less$/,
            use: [{
                loader: 'style-loader'
            }, {
                loader: 'css-loader', options: {
                    url: false,
                    sourceMap: true
                }
            }, {
                loader: 'less-loader', options: {
                    relativeUrls: false,
                    sourceMap: true
                }
            }]
        },
        {
            test: /\.(jpe?g|png|gif)(\?.*)?$/i,
            use: [{
                loader: 'file-loader',
                options: {name: '[path][name].[hash].[ext]'}
            }]
        },
        {
            test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
            use: {
                loader: 'file-loader',
                options: {
                    name: '[name].[ext]',
                    outputPath: 'fonts/'
                }
            }

        },
        {
            test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
            use: [
                {
                    loader: 'url-loader',
                    options: {limit: 10000, mimetype: 'application/octet-stream'}
                }
            ]
        },
        {
            test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
            use: [
                {
                    loader: 'file-loader'
                }
            ]
        },
        {
            test: /\.svg$/i,
            loader: 'raw-loader'
        },
        {
            test: require.resolve('angular'),
            use: [
                {loader: 'expose-loader', options: 'angular'},
            ]
        },
        {
            test: require.resolve('jquery'),
            use: [
                {loader: 'expose-loader', options: '$'},
                {loader: 'expose-loader', options: 'jQuery'},
            ]
        },
        {
            test: require.resolve('lodash'),
            use: [
                {loader: 'expose-loader', options: '_'},
            ]
        },
        {
            test: require.resolve('moment'),
            use: [
                {loader: 'expose-loader', options: 'moment'},
            ]
        },
        {
            test: /\.html$/,
            use: [{
                loader: 'raw-loader',
                options: {name: '[path][name].[hash].[ext]'}
            }]
        }
    ]
},

plugins: [
    new HtmlWebpackPlugin({
        template: path.join(appPath, 'index.html')
    }),

    new webpack.DefinePlugin({
        INJECT_REGEX_HERE: JSON.stringify(patterns)
    }),

    new CopyWebpackPlugin([
        {from: 'app/images', to: 'assets/images'},
        {from: 'app/fonts', to: 'assets/fonts'},
        {from: 'app/templates', to: 'assets/templates'},
        {from: 'app/silent-callback.html', to: 'silent-callback.html'},
        {from: 'node_modules/font-awesome/css', to: 'assets/font-awesome/css'},
        {from: 'node_modules/font-awesome/fonts', to: 'assets/font-awesome/fonts'},
        {from: 'node_modules/angular-ui-grid/fonts', to: 'assets/fonts'},
        {from: 'node_modules/d3/d3.min.js', to: 'assets/d3'}
    ]),

    new MiniCssExtractPlugin({
        filename: '[name].[hash].css',
        chunkFilename: '[id].[hash].css'
    }),

    new OpenBrowserPlugin({url: 'http://localhost:1337'})
],

devtool: isProduction ? 'source-map' : 'inline-source-map',

devServer: {
    port: 1337
},

optimization: {
    splitChunks: {
        cacheGroups: {
            commons: {
                test: /[\\/]node_modules[\\/]/,
                name: 'vendors',
                chunks: 'all'
            }
        }
    }
}

};

if (RemoteServer) {
     console.log('running with remote server', RemoteServer);
     config.devServer.proxy = {
    '/occm/*': 'http://' + RemoteServer
    };
 }

if (isProduction) {
config.plugins.push(
    new CleanWebpackPlugin(buildPath)
    );
}

module.exports = config;

【问题讨论】:

  • 您找到解决方案了吗?我正在寻找同样的东西
  • 作为一个选项,您可以将所有 html 模板内联到 js 中。这就是我们在应用中所做的。
  • @PetrAveryanov 你如何处理 ngIncludes(如果有的话)?
  • 我们只有“file-local” ng-includes,没有问题。 (我们直接把全局模板放到templateCache中)

标签: javascript angularjs webpack


【解决方案1】:

几年前我进行了类似的迁移,我不需要那种类型的解决方案。我的目标是将每个组件封装为一个模块,然后尽可能地延迟加载。

// webpack config
{
  test: /\.html$/,
  use: ['html-loader'],
},

然后在每个组件中我只需要样式和模板,例如:

require('./_proposal-page.scss');

(function() {
  'use strict';
  angular.module('component.myComponent', []).component('myComponent', {
    template: require('./proposal-page.html'),
    controller: MyController,
  });

  /** @ngInject */
  function MyController($log) {
    const $ctrl = this;
    $ctrl.$onInit = function() {
      $log.log('$onInit myComponent');
    }
  }
})();
if (typeof module !== 'undefined' && typeof exports !== 'undefined' && module.exports === exports) {
  module.exports = 'component.myComponent';
}

Webpack 检测需求并将每个.html 文件导出为一个模块,它运行顺利。

【讨论】:

    【解决方案2】:

    使用 Webpack 的主要好处之一是减少了浏览器为呈现您的应用程序而必须执行的请求数量,并使您的应用程序启动更快。 为了实现这一点,它将相关资源组合在“块”中,这些资源在一个请求中一起加载。单独加载所需的单个文件,如 HTML 模板(没有特定原因)在这里可能被视为反模式。

    最佳实践是将所有相关的 JS、HTML 和 CSS 代码组合在一个大包中,该包只加载一次,有时(对于较大的应用程序)为来自 node_modules 的代码提供第二个“供应商”包,从而加快开发速度,因为这块不会经常更改。

    替代方案:

    因此,在您的情况下,如果没有特定原因将事物分开(您没有写过),我宁愿建议将 HTML 与控制代码放在一个块中,而不是单独加载 HTML 文件。

    一个好的和简单的起点是只构建两个块。用以下代码替换整个优化块:

    optimization: {
      splitChunks: {
        cacheGroups: {
          commons: {
            test: /[\\/]node_modules[\\/]/,
            name: 'vendor',
            chunks: 'all'
          }
        }
      }
    },
    

    这将构建两个块:一个用于所有 JS 和 HTML 文件的主要块,另一个用于 node_modules 文件夹中的所有内容。

    这样您就不必再担心 HTML 文件的浏览器缓存了,因为它们是在您的主块中构建的,而且,作为一个好处,您的应用将启动得更快。

    【讨论】:

    • 基本的一点是,webpack 会自动为你处理这个,你不需要自己构建哈希。
    猜你喜欢
    • 2017-04-03
    • 2019-12-20
    • 1970-01-01
    • 1970-01-01
    • 2016-05-21
    • 2016-07-02
    • 1970-01-01
    • 2023-03-10
    • 2019-12-30
    相关资源
    最近更新 更多