Как прошить tinymce в webpack?

Я пытаюсь получить tinymce, признанный webpack. Он устанавливает свойство с именем tinymce на window, поэтому, по-видимому, один параметр имеет значение require(), используя синтаксис, подобный этому (описанный в нижней части раздела EXPORTING из документов webpack):

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

Но в этом примере, как ./file.js разрешено? Я установил tinymce через npm, и я не могу понять, как указать правильный путь к файлу tinymce.js.

Независимо от того, я бы предпочел справиться с этим в своей конфигурации и иметь возможность просто require('tinymce'), если это возможно, поэтому я установил exports-loader и добавил следующую конфигурацию (на основе это обсуждение):

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

К сожалению, это не работает. Что не так с моей конфигурацией?

Ответ 1

Модуль tinymce на npm не может быть необходим напрямую, но содержит 4 разных дистрибутива библиотеки. А именно:

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

Чтобы сделать require('tinymce') в своем коде, вы можете добавить псевдоним в свою конфигурацию webpack, а также пользовательский загрузчик для вашего выбора по выбору.

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 своим распределением по выбору.

Ответ 2

Как и @cchamberlain, я закончил использование загрузчика script для 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

Я получил это, чтобы он работал подобно тому, как я связываю 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'
                        ]
          }

Это работает для меня так же, как и с script из CDN, но теперь у меня были ошибки, потому что он не мог найти мои темы/плагины/скины из моего местоположения node_modules. Он искал их по пути /assets/plugins, /assets/themes, /assets/skins (я использую общедоступный путь webpack /assets/).

Я разрешил вторую проблему путем отображения выражения для того, чтобы эти два маршрута статически ставились так (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.

Ответ 4

Мне удалось интегрировать tinyMCE в мой проект Angular 2/TypeScript, используя импорт-загрузчик и экспорт-загрузчик и плагин copy-webpack.

Сначала убедитесь, что доступны необходимые зависимости и часть файла 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

Затем добавьте требуемый загрузчик в раздел загрузчиков конфигурации вашего веб-пакета:

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

Чтобы сделать copyWebpackPlugin доступным в вашей конфигурации webpack, импортируйте его в заголовочную часть файла конфигурации webpack:

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

И, как прокомментировал Петри Риханен, добавьте следующую запись в раздел плагинов вашей конфигурации веб-пакета:

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 также доступны в вашем веб-пакете.

Наконец, чтобы импортировать tinyMCE в ваш компонентный файл Angular 2, добавьте

require('tinymce')

declare var tinymce: any;

в разделе импорта, и tinyMCE готов к использованию.

Ответ 5

В качестве дополнения к этому ответу (спасибо Петри Ryhänen), я хочу добавить свой copyWebpackPlugin и tinymce.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}'
}