【问题标题】:How to shim tinymce in webpack?如何在 webpack 中填充 tinymce?
【发布时间】:2015-08-11 22:12:57
【问题描述】:

我正在尝试让 webpack 识别 tinymce。它在window 上设置了一个名为tinymce 的属性,因此显然一种选择是使用这样的语法require() 它(在webpack 文档的EXPORTING section 底部描述):

require("imports?window=>{}!exports?window.XModule!./file.js

但是在这个例子中,./file.js 是如何解析的呢?我通过 npm 安装了 tinymce,但我不知道如何指定 tinymce.js 文件的正确路径。

无论如何,我宁愿在我的配置中处理这个问题,如果可能的话,我只能使用require('tinymce'),所以我安装了exports-loader,并将以下内容添加到我的配置中(基于this discussion):

module: {
    loaders: [
        {
            test: /[\/]tinymce\.js$/,
            loader: 'exports?tinymce'
        }
    ]
}

很遗憾,这不起作用。我的配置有什么问题?

【问题讨论】:

    标签: javascript node.js tinymce webpack shim


    【解决方案1】:

    npm 上的 tinymce 模块不能直接需要,但包含 4 个不同的库分布。即:

    • tinymce/tinymce.js
    • tinymce/tinymce.min.js
    • tinymce/tinymce.jquery.js
    • tinymce/tinymce.jquery.min.js

    为了能够在您的代码中执行 require('tinymce'),您可以在您的 webpack 配置中添加 an alias,以及为您选择的分发版添加自定义加载器。

    resolve: {
      alias: {
        // require('tinymce') will do require('tinymce/tinymce') 
        tinymce: 'tinymce/tinymce',
      },
    },
    module: {
      loaders: [
        {
          // Only apply on tinymce/tinymce
          include: require.resolve('tinymce/tinymce'),
          // Export window.tinymce
          loader: 'exports?window.tinymce',
        },
      ],
    },
    

    您可以将tinymce/tinymce 替换为您选择的发行版。

    【讨论】:

    • 感谢您的回复。现在 webpack 在我 require('tinymce') 的文件中告诉我 Cannot resolve module 'imports'。我确实安装了imports-loader,所以我不确定还有什么问题。
    • 您可能必须提供完整的模块名称。 imports-loader?window=>{}!exports-loader?window.tinyMCE![dist]
    • 是的,imports-loader的全名工作:tinymce: 'imports-loader?window=>{}!exports?window.tinymce!tinymce/tinymce.js'
    • 虽然我不再遇到构建问题,但我今天发现 tinymce 正在作为函数导入,并且它没有任何我期望的方法(例如init() 实际创建所见即所得实例的方法)。如何告诉 webpack 将 tinymce 作为对象导入并保留其所有方法?
    • 可以发誓resolve.alias 值支持加载程序,但似乎它们不支持(请参阅this issue)。我之前的建议导致客户端需要imports-loader 而不是tinymce。我已经编辑了我的答案。
    【解决方案2】:

    就像 @cchamberlain 一样,我最终使用了 tinymce 的脚本加载器,但是为了加载默认情况下不需要的插件和其他资源,我使用 CopyWebpackPlugin 而不是 ES6 以获得更多可配置的解决方案。

    var copyWebpackPlugin = require('copy-webpack-plugin');
    module.exports = {
    //...
      plugins: [
        new copyWebpackPlugin([
          { from: './node_modules/tinymce/plugins', to: './plugins' },
          { from: './node_modules/tinymce/themes', to: './themes' },
          { from: './node_modules/tinymce/skins', to: './skins' }
        ])
      ]
    };
    

    【讨论】:

      【解决方案3】:

      通过使用 imports-loader 和 exports-loader 以及 copy-webpack-plugin,我能够将 tinyMCE 集成到基于 Angular 2/TypeScript 的项目中。

      首先确保必要的依赖项可用并且是项目的packages.json文件的一部分:

      npm i tinymce --save
      npm i exports-loader --save-dev
      npm i imports-loader --save-dev    
      npm i copy-webpack-plugin --save-dev
      

      然后将所需的加载器添加到 webpack 配置的加载器部分:

          loaders: [          
              {
                  test: require.resolve('tinymce/tinymce'),
                  loaders: [
                      'imports?this=>window',
                      'exports?window.tinymce'
                  ]
              },
              {
                  test: /tinymce\/(themes|plugins)\//,
                  loaders: [
                      'imports?this=>window'
                  ]
              }]
      

      要让 copyWebpackPlugin 在你的 webpack 配置中可用,请将其导入 webpack 配置文件的 header 部分:

      var copyWebpackPlugin = require('copy-webpack-plugin');
      

      并且,正如 Petri Ryhänen 评论的那样,将以下条目添加到 webpack 配置的插件部分:

      plugins: [
          new copyWebpackPlugin([
              { from: './node_modules/tinymce/plugins', to: './plugins' },
              { from: './node_modules/tinymce/themes', to: './themes' },
              { from: './node_modules/tinymce/skins', to: './skins' }
          ])
      ]
      

      此步骤可确保您的 webpack 中也有(必需的)tinyMCE 插件。

      最后在你的Angular 2组件文件中导入tinyMCE,添加

      require('tinymce')
      
      declare var tinymce: any;
      

      到导入部分,tinyMCE 就可以使用了。

      【讨论】:

      • 很棒的答案,效果很好。注意,now需要写'imports-loader?this=>window',以此类推。
      【解决方案4】:

      我让它的工作方式类似于我捆绑 React 的方式,以确保我不会在 DOM 中获得两个单独的实例。我在导入/导出/公开加载器方面遇到了一些问题,所以我使用了脚本加载器。

      在我的设置中,我有一个公共块,我严格用于供应商(React / tinymce)。

         entry: { 'loading': '../src/app/entry/loading'
                , 'app':  '../src/app/entry/app'
                , 'timeout': '../src/app/entry/timeout'
                , 'commons':  [ 'expose?React!react'
                              , 'expose?ReactDOM!react-dom'
                              , 'script!tinymce/tinymce.min.js'
                              ]
                }
      

      这对我的工作方式与包含来自 CDN 的脚本的工作方式相同,但是我现在遇到了错误,因为它无法从我的 node_modules 位置找到我的主题/插件/皮肤路径。它在路径 /assets/plugins/assets/themes/assets/skins 上寻找它们(我使用 webpack 公共路径 /assets/)。

      我通过映射 express 解决了第二个问题,像这样(es6)静态地为这两个路由提供服务:

        const NODE_MODULES_ROOT = path.resolve(__dirname, 'node_modules')
        const TINYMCE_PLUGINS_ROOT = path.join(NODE_MODULES_ROOT, 'tinymce/plugins')
        const TINYMCE_THEMES_ROOT = path.join(NODE_MODULES_ROOT, 'tinymce/themes')
        const TINYMCE_SKINS_ROOT = path.join(NODE_MODULES_ROOT, 'tinymce/skins')
      
        router.use('/assets/plugins', express.static(TINYMCE_PLUGINS_ROOT))
        router.use('/assets/themes', express.static(TINYMCE_THEMES_ROOT))
        router.use('/assets/skins', express.static(TINYMCE_SKINS_ROOT))
      

      执行此操作后,window.tinymce / window.tinyMCE 均已定义且功能与 CDN 相同。

      【讨论】:

        【解决方案5】:

        作为this answer 的补充(感谢Petri Ryhänen),我想添加我的copyWebpackPlugintinymce.init() 配置调整。

        new copyWebpackPlugin([{
          context: './node_modules/tinymce/skins/lightgray',
          from: './**/*',
          to: './tinymce/skin',
        }]),
        

        通过此配置,您将获得{output}/tinymce/skin 文件夹中的所有皮肤文件。

        然后你可以像这样初始化tinymce:

        import tinymce from 'tinymce/tinymce';
        
        // A theme is also required
        import 'tinymce/themes/modern/theme';  // you may change to 'inlite' theme
        
        // Any plugins you want to use has to be imported
        import 'tinymce/plugins/advlist/plugin';
        // ... possibly other plugins
        
        // Then anywhere in this file you can:
        tinymce.init({
          // ... possibly other options
          skin_url: '/tinymce/skin',  // <-- !!! here we tell tinymce where
                                      //         to load skin files from
          // ... possibly other options
        });
        

        有了这个,我的开发和生产版本都可以正常工作。

        【讨论】:

          【解决方案6】:

          我们使用 TinyMCE jQuery 4.1.6 并且接受的答案对我们不起作用,因为 window 似乎被 TinyMCE 在其他位置使用(例如 window.setTimeout)。此外,document 未填充似乎会导致问题。

          这对我们有用:

          alias: {
              'tinymce': 'tinymce/tinymce.jquery.js'
          }
          
          module: {
              loaders: [
                  {
                      test: /tinymce\/tinymce\.jquery\.js/,
                      loader: 'imports?document=>window.document,this=>window!exports?window.tinymce'
                  }
              ]
          }
          

          像这样加载你的插件:

          {
              test:  /tinymce\/plugins/,
              loader: 'imports?tinymce,this=>{tinymce:tinymce}'
          }
          

          【讨论】:

          • 在使用 webpack 时,我无法在 jQuery 对象上调用 tinymce 函数。 tinyMCE 和 tinymce 绑定到窗口。尝试在 jQuery 对象上调用 tinymce 时收到 $(...).tinymce is not a function
          猜你喜欢
          • 1970-01-01
          • 2016-12-21
          • 2011-08-20
          • 2021-02-09
          • 2019-06-12
          • 1970-01-01
          • 2018-05-28
          • 2015-04-25
          • 1970-01-01
          相关资源
          最近更新 更多