如何在Webpack中使用shim来加载Tinymce?

6个回答

11

在npm上,无法直接require tinymce模块,但它包含4个不同的库文件分发版本,分别是:

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

要在您的代码中使用 require('tinymce'),您可以在webpack配置中添加别名(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,所以我不确定还有什么其他问题。 - Rob Johansen
你可能需要提供完整的模块名称。imports-loader?window=>{}!exports-loader?window.tinyMCE![dist] - Alexandre Kirszenberg
是的,imports-loader 的完整名称有效:tinymce: 'imports-loader?window=>{}!exports?window.tinymce!tinymce/tinymce.js' - Rob Johansen
虽然我不再遇到构建问题,但今天我发现tinymce被导入为一个函数,并且它没有我期望的任何方法(例如实际创建WYSIWYG实例的init()方法)。我该如何告诉webpack将tinymce作为对象导入并保留其所有方法? - Rob Johansen
本以为 resolve.alias 支持加载器,但它们似乎不支持(见这个问题)。我的先前建议导致客户端需要 imports-loader 而非 tinymce。我已经编辑了我的回答。 - Alexandre Kirszenberg
无论我如何尝试 shim,都一直出现错误。最终使用了 CDN。这样可以正常工作。 - Alex

11

就像 @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' }
    ])
  ]
};

4

我使用imports-loader、exports-loader和copy-webpack-plugin,在我的基于Angular 2/TypeScript的项目中成功集成了tinyMCE。

首先确保必要的依赖项可用,并且已包含在您项目的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部分中添加必要的加载器:
    loaders: [          
        {
            test: require.resolve('tinymce/tinymce'),
            loaders: [
                'imports?this=>window',
                'exports?window.tinymce'
            ]
        },
        {
            test: /tinymce\/(themes|plugins)\//,
            loaders: [
                'imports?this=>window'
            ]
        }]

为了在Webpack配置中使用copyWebpackPlugin,请在Webpack配置文件的头部导入它:
var copyWebpackPlugin = require('copy-webpack-plugin');

同时,正如Petri Ryhänen所评论的那样,在你的webpack配置文件的plugins部分添加以下条目:

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

这一步确保了TinyMCE所需的插件在您的webpack中也可用。

最后,在您的Angular 2组件文件中导入TinyMCE,请添加:

require('tinymce')

declare var tinymce: any;

转到导入部分,tinyMCE即可使用。


很棒的回答,它运行得非常好。 注意,现在你需要写 'imports-loader?this=>window'等等。 - Drasill

3

我把这个工作类比React捆绑,以确保DOM中没有两个单独的实例。我遇到了一些导入/导出/公开加载器的问题,所以我使用了script-loader。

在我的设置中,我有一个专门用于供应商(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相同的功能。


1
作为此答案的补充(感谢Petri Ryhänen),我想添加我的copyWebpackPlugintinymce.init()配置调整。请注意,保留html标签。
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
});

我现在既有开发版又有生产版,两者都正常运行。


0

我们使用TinyMCE jQuery 4.1.6,但是接受的答案对我们没有用,因为TinyMCE在其他位置(例如window.setTimeout)中似乎使用了window。此外,未进行shim的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绑定到window。当尝试在jQuery对象上调用tinymce时,我收到“$(...).tinymce不是函数”的错误提示。 - Chris McKnight

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接