代码之家  ›  专栏  ›  技术社区  ›  kolistivra

通过Webpack创建带有哈希的供应商包并在同构应用程序中使用它

  •  0
  • kolistivra  · 技术社区  · 6 年前

    我有三种不同的webpack配置(client.webpack.js、server.webpack.js和vendor.webpack.js),vendor.webpack.js用于创建供应商包,因为它们很少更改,占用大量空间。我们使用 DllPlugin 要生成它,并通过 DllReferencePlugin .

    我想做的改进是向供应商文件添加一个哈希,例如,我想创建vendor.348723.js,而不是vendor.js。这样做的原因是为了改进缓存。

    棘手的部分是我们的应用程序是同构的,这意味着HTML的生成是由服务器(node.js+react,server.webpack.js)在运行时完成的。在服务器内部,在JS文件中,我们创建模板, <script type='text/javascript' src='/vendor.js'></script> 在某个地方。我的问题是,如何注入vendor.somehash.js?

    我尝试过但失败了:

    扩展apipplugin

    Caching with Webpack, [hash] value inside index source code, using React.js

    使用vendor.webpack.js中的extendedapiplugin,并尝试使用 __webpack_hash__ 生成HTML模板时,例如 <script type='text/javascript' src='/vendor.${__webpack_hash__}.js'></script> 由于我有两种不同的webpack配置,并且我在vendor.webpack.js中生成了散列,所以在生成HTML模板时服务器无法识别散列。

    其他相关信息

    我们不使用HTML Webpack插件——我认为它不适用,因为我们有一个同构的应用程序。( Webpack - Best way to update HTML to include latest [hashed] bundles )

    我看的其他相关页面

    Link css filename with hash to index.html after the Extract Text Plugin

    vendor.webpack.js供应商.webpack.js

    const path = require('path')
    const webpack = require('webpack')
    
    module.exports = {
      name: 'vendor',
      mode: 'development',
      entry: [
        'axios',
        'babel-polyfill',
        'material-ui',
        'classnames',
        'mixpanel-browser',
        'ramda',
        'react',
        'react-dropzone-component',
        'react-dom',
        'react-ga',
        'react-helmet',
        'react-redux',
        'react-router-dom',
        'react-router-redux',
        'redux',
        'redux-thunk',
        'redux-saga'
      ],
      output: {
        path: path.resolve(__dirname, '../client'),
        filename: 'vendor.js',
        library: 'vendor_[hash]'
      },
      plugins: [
        new webpack.DllPlugin({
          name: 'vendor_[hash]',
          path: path.resolve(__dirname, '../client/manifest.json')
        }),
        new webpack.DefinePlugin({
          'process.env': {
            NODE_ENV: JSON.stringify(process.env.NODE_ENV)
          }
        }),
        new webpack.ExtendedAPIPlugin(),
        new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
      ]
    }
    

    客户端.webpack.js

    require('env2')('env.json')
    const path = require('path')
    const webpack = require('webpack')
    const StatsPlugin = require('stats-webpack-plugin')
    const MiniCssExtractPlugin = require('mini-css-extract-plugin')
    const merge = require('webpack-merge')
    const baseConfig = require('./base.js')
    
    module.exports = merge(baseConfig.moduleRules, {
      name: 'client',
      mode: 'development',
      target: 'web',
      // Good compromise between speed and quality, suitable for local development.
      devtool: 'cheap-module-eval-source-map',
      entry: [path.resolve(__dirname, '../app/index.js')],
      output: {
        filename: 'client.[chunkhash].js',
        chunkFilename: 'client.[chunkhash].js',
        path: path.resolve(__dirname, '../client'),
        publicPath: '/'
      },
      watchOptions: {
        poll: true
      },
      plugins: [
        new MiniCssExtractPlugin({
          filename: 'style.css'
        }),
        new webpack.DllReferencePlugin({
          manifest: path.resolve(__dirname, '../client/manifest.json')
        }),
        new StatsPlugin('stats.json'),
        new webpack.DefinePlugin({
          'process.env': {
            NODE_ENV: JSON.stringify('development')
          }
        })
      ],
      optimization: {
        runtimeChunk: 'single'
      }
    })
    

    服务器.webpack.js

    const fs = require('fs')
    const path = require('path')
    const webpack = require('webpack')
    const MiniCssExtractPlugin = require('mini-css-extract-plugin')
    const merge = require('webpack-merge')
    const baseConfig = require('./base.js')
    
    const res = p => path.resolve(__dirname, p)
    
    const modeModules = res('../node_modules')
    const entry = res('../lib/routes/resources/reactUrls.js')
    const output = res('../buildServer')
    
    // if you're specifying externals to leave unbundled, you need to tell Webpack
    // to still bundle `react-universal-component`, `webpack-flush-chunks` and
    // `require-universal-module` so that they know they are running
    // within Webpack and can properly make connections to client modules:
    const externals = fs
      .readdirSync(modeModules)
      .filter(x => !/\.bin|react-universal-component|webpack-flush-chunks/.test(x))
      .reduce((externals, mod) => {
        externals[mod] = `commonjs ${mod}`
        return externals
      }, {})
    
    externals['react-dom/server'] = 'commonjs react-dom/server'
    
    module.exports = merge(baseConfig.commons, {
      name: 'server',
      mode: 'development',
      target: 'node',
      // Good compromise between speed and quality, suitable for local development.
      devtool: 'cheap-module-eval-source-map',
      entry: [entry],
      externals,
      output: {
        path: output,
        filename: '[name].js',
        libraryTarget: 'commonjs2'
      },
      plugins: [
        new MiniCssExtractPlugin({
          filename: '/style.css'
        }),
        new webpack.optimize.LimitChunkCountPlugin({
          maxChunks: 1
        }),
        new webpack.EnvironmentPlugin(['NODE_ENV'])
      ]
    })
    
    1 回复  |  直到 6 年前
        1
  •  0
  •   kolistivra    6 年前

    WebpackManifestPlugin 可用于解决此问题。