【问题标题】:Automatically loading externals with Webpack使用 Webpack 自动加载外部组件
【发布时间】:2016-09-08 23:21:04
【问题描述】:

我进行了一些搜索,但想知道这里是否有一个优雅的解决方案。在构建 Webpack 应用程序时,通常会有不需要编译/捆绑的依赖项,例如 jQuery、React、ReactDOM、Angular 或 Bootstrap,仅举几例。您可以在 externals 对象的 Webpack 配置文件中列出这些库,但 externals 只是假设这些库将在运行时作为命名空间全局变量可用。

这意味着对于externals 哈希中的每个条目,您还需要在 HTML 中添加一个脚本标记。如果您引用外部 CDN,这是有道理的,但我认为如果您只想从 node_modules 的库中复制一些 dist 文件,这可以自动化。

我一直在寻找有关如何执行此操作的示例,但我还没有看到任何示例。我搞砸了external-loader,但我没有运气集成它(文档似乎没有提供完整的示例)。

基本上,这需要发生:

  1. 不应捆绑的库应添加到 resolve.alias,例如{"react": "react/dist/react.js"}
  2. 加载程序将 dist 文件复制到公共目录(也许这可以通过 file-loader 完成?)
  3. HTML 加载器或插件会在 bundle.js 脚本标签之前插入脚本标签

如果不存在这样的东西,我可能会考虑尝试制作一个;我只是在这里发布这个,看看是否有人可能知道预烘焙的解决方案,因为这似乎是构建 Web 应用程序的常见问题,我想我可能遗漏了一些东西。

【问题讨论】:

    标签: javascript reactjs webpack


    【解决方案1】:

    var path = require("path");
    var webpack = require('webpack');
    var HtmlWebpackPlugin = require('html-webpack-plugin');
    var HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin');
    var ExtractTextPlugin = require('extract-text-webpack-plugin');
    var helpers = require('./helpers');
    
    var WebpackNotifierPlugin = require('webpack-notifier');
    
    module.exports = {
        entry: {
            'index-ref': './app/index-ref.ts',
            'vendor': './app/vendor.ts',
            'app': './app/main.ts',
        },
    
        resolve: {
            extensions: ['', '.ts', '.js']
        },
    
        module: {
            loaders: [
              {
                  test: /\.ts$/,
                  loaders: ['awesome-typescript-loader', 'angular2-template-loader']
              },
              {
                  test: /\.html$/,
                  loader: 'html'
              },
              {
                  test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
                  loader: 'file?name=assets/[name].[hash].[ext]'
              },
              {
                  test: /\.css$/,
                  exclude: helpers.root('app'),
                  loader: ExtractTextPlugin.extract('style', 'css?sourceMap')
              },
              {
                  test: /\.css$/,
                  include: helpers.root('app'),
                  loader: 'raw'
              }
            ]
        },
    
        plugins: [
          new webpack.optimize.CommonsChunkPlugin({
              name: ['app', 'vendor', 'index-ref']
          }),
    
          new HtmlWebpackPlugin({
              filename: '../index.html',
              template: 'template' + '/default.html',
              lib: ['jQuery'],
              chunks: ['entry-name']
          }),
          new HtmlWebpackExternalsPlugin([
            // Using a CDN for a JS library 
            {
                name: 'jquery',
                var: 'jQuery',
                url: 'https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.js'
            }
          ],
          {
              basedir: 'node_modules',
              dest: 'lib'
          }),
    
              new WebpackNotifierPlugin()
        ]
    };

    我错过了什么吗?

    【讨论】:

      【解决方案2】:

      我没有找到预先存在的解决方案,所以我写了一个插件来补充 HtmlWebpackPlugin。它接受一个外部数组并将脚本/链接标签附加到 HTML 文件,生成外部哈希,并且可以使用 CDN 或本地文件。

      https://github.com/mmiller42/html-webpack-externals-plugin

      【讨论】:

      • 你有这方面的工作样本吗?我试图添加一个 jquery cdn,但我在 index.html 中的任何地方都看不到它
      • 您好 Miller,当我使用您的插件从 CDN 加载某些库时,chrome 报告说库未定义。我在你的 github 上报告了一个问题。那我做错了什么?
      【解决方案3】:

      如果您不想添加额外的包膨胀,那么HtmlWebpackPlugin 具有模板功能,因此您可以执行以下操作:

      //template.html
      
      <html>
        <head>
           <%= htmlWebpackPlugin.options.externals %>
        </head>
        ...
      </html>
      

      然后在你的 webpack 配置中像这样:

      //webpack.config.js
      
      const EXTERNALS = [
        {
          name: 'react',
          globalVarName: 'React',
          src: 'https://cdn.example.com/react@18',
        },
        ...
      ]
      
      
      
      module.exports = {
        ...,
        plugins: [
          new HtmlWebpackPlugin({
            filename: 'index.html',
            template: 'template.html',
            externals: EXTERNALS.reduce(
              (scripts, external) => (
                `${scripts}<script src="${external.src}"></script>`
              ), ''
            )
          })
        ],
        externals: EXTERNALS.reduce(
          (res, external) => ({
            ...res,
            [external.name]: external.globalVarName,
          }), {}
        ),
      }
      

      (你显然可以在 webpack 配置文件中添加任何你想要的环境定制/更详细的细节/等等。)

      编辑:

      对于一些额外的华丽,你还可以从你的 node_modules 中获取当前的包版本,而不是将它们硬编码到 webpack 文件中:

      const fs = require('fs')
      
      function getPackageVersion(packageName) {
        const pkgPath = `node_modules/${packageName}`
        const pkg = JSON.parse(fs.readFileSync(`${pkgPath}/package.json`, 'utf8'))
        return pkg['version']
      }
      

      【讨论】:

        猜你喜欢
        • 2018-09-13
        • 2016-02-18
        • 2015-12-07
        • 2020-05-19
        • 2018-06-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多