Как использовать библиотеку из CDN в проекте Webpack в продакшене

Я хотел бы использовать react.min.js из CDN в рабочей среде (например, https://unpkg.com/[email protected]/dist/react.min.js)

Каков наилучший способ заставить Webpack преобразовать мои операторы import React from 'react' в const React = window.React вместо того, чтобы встраивать node_modules/react в пакет?

Я делал это с resolve.alias вот так:

In index.html:

<head>
  <script type="text/javascript" src="https://unpkg.com/[email protected]/dist/react.min.js"></script>
  <script type="text/javascript" src="/assets/bundle.js"></script>
</head>

In webpack.prod.config.js:

alias: {
  react$: './getWindowReact',
},

getWindowReact.js:

module.exports = window.React;

Примечание. В старом вопросе я не понимал, что сборка React в пакет Webpack с NODE_ENV=production удалит проверки propTypes. Один из ответов посвящен этому.


person Andy    schedule 22.07.2015    source источник


Ответы (3)


В конфигурации вашего веб-пакета вы можете использовать параметр externals, который будет импортировать модуль из среды вместо того, чтобы пытаться разрешить его обычным образом:

// webpack.config.js
module.exports = {
  externals: {
    'react': 'React'
  }
  ...
};

Подробнее читайте здесь: https://webpack.js.org/configuration/externals/

person franky    schedule 22.07.2015
comment
Получается, что я ошибался в том, что React создавался с помощью Webpack, так что это не сработает. Но это правильный ответ для использования модуля, созданного с помощью Webpack, поэтому я приму этот ответ. - person Andy; 24.07.2015
comment
@ Энди, возможно, я не совсем понимаю ваш комментарий, но то, что было предложено здесь, не требует, чтобы загружаемая библиотека была собрана с помощью Webpack. Все, что делает этот пример externals, это говорит веб-пакету, если модуль запрашивает react, возвращает window.React. - person Aaronius; 22.09.2016
comment
@ Аарониус, да, извините, я неправильно понял веб-пакет externals в то время ... документы для них довольно неудобны. - person Andy; 23.09.2016
comment
Когда вы определили 'react': 'React', откуда webpack знает, откуда его взять? Я имею в виду, может быть много версий или названий - person Raz; 01.07.2019
comment
@Raz 'react': 'React' означает, что когда я импортирую from 'react', вместо этого ищу window.React. Ключ — это имя пакета, значение — это имя глобального свойства. - person Jacob Raihle; 11.09.2020

Я создал https://github.com/mastilver/dynamic-cdn-webpack-plugin который делает именно это из коробки

const path = require('path')
const HTMLWebpackPlugin = require('html-webpack-plugin')
const DynamicCDNWebpackPlugin = require('dynamic-cdn-webpack-plugin')

module.exports = {
  entry: './main.js',
  output: {
    path: path.join(__dirname, 'build'),
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /node_modules/,
        use: {
          loader: 'babel-loader'
        }
      }
    ]
  },
  plugins: [
    new HTMLWebpackPlugin(),
    new DynamicCDNWebpackPlugin()
  ]
}

Динамически добавит URL-адреса unpkg.org и добавит соответствующий код в ваш пакет для загрузки библиотек из global.

person mastilver    schedule 04.07.2017
comment
блять, это отличная идея! Я использую https://github.com/kossnocorp/assets-webpack-plugin вместо плагина манифеста, знаете ли вы, будет ли ваш плагин работать и с assets-webpack-plugin? - person Andy; 07.07.2017
comment
@Энди, я не пробовал, но думаю, что да. Если нет, не стесняйтесь поднимать вопрос :) - person mastilver; 07.07.2017
comment
@mastilver path куда ведет ссылка CDN? - person Q.H.; 28.07.2017
comment
@Q.H. ваши ссылки не входят в index.html созданный html-webpack-plugin - person mastilver; 31.07.2017
comment
Это работает отлично. В modules-cdn не так много предопределенных модулей, и не совсем очевидно, как написать собственный преобразователь, чтобы заполнить пустоту — пример в файле readme был бы великолепен! Я пошел с if (modulePath == 'lodash') return { name: 'lodash', url: 'https://unpkg.com/lodash@' + version + '/lodash.min.js' };, и пока это работает. - person Roman Starkov; 12.08.2017
comment
@RomanStarkov Почти! :) Должно быть: if (modulePath == 'lodash') return { name: 'lodash', url: 'https://unpkg.com/lodash@' + version + '/lodash.min.js', version: version, var: '_' }; Но так он заменит module-to-cdn... Могу я спросить, почему вы не отправили PR на module-to-cdn? Вы не один такой, и я пытаюсь понять, как мне сделать проще? - person mastilver; 16.08.2017
comment
Да, я понял часть var вскоре после этого, но больше не мог редактировать комментарий. Мне нужно было это прямо здесь и сейчас, так что пиар был бы слишком медленным. По факту... просто смесь лени, занятости и ощущения, что нужно больше работать. Нужно ли перечислять пакеты? Я считаю, что unpkg может похвастаться предсказуемыми URL-адресами, поэтому вы можете просто создать его и надеяться, что пакет там. - person Roman Starkov; 16.08.2017
comment
Нет, если вы посмотрите на github.com/mastilver/module- to-cdn/blob/master/modules.json вы можете видеть, что существует множество разновидностей (даже для одного и того же пакета). Даже М. Джексон, автор unpkg, просмотрел его и ничего не упомянул. Мне нужно найти способ упростить редактирование :) - person mastilver; 16.08.2017
comment
@mastilver Как этот плагин определяет, какую версию модуля, скажем, React, следует загрузить? Нужно ли мне по-прежнему указывать правильную версию в зависимостях package.json? Или я могу вообще исключить React из package.json? - person hazardous; 29.08.2017
comment
@hazardous ваше приложение должно работать одинаково с этим плагином или без него, поэтому добавьте реакцию в свой package.json . Что происходит, так это то, что он требует package.json вашей зависимости и использует указанную там версию (github.com/mastilver/dynamic-cdn-webpack-plugin/blob/) - person mastilver; 29.08.2017

Все части кодовой базы React, предназначенные только для разработки, такие как проверки PropType, защищены:

if ("production" !== process.env.NODE_ENV) {
  ..
}

Чтобы удалить их из React в вашей собственной сборке, создав эквивалент минимизированной сборки React в собственном пакете, используйте DefinePlugin для замены ссылок на process.env.NODE_ENV на "production".

plugins: [
  // ...
  new webpack.DefinePlugin({
    'process.env.NODE_ENV': JSON.stringify('production')
  }),
  new webpack.optimize.UglifyJsPlugin({
    compressor: {
      warnings: false
    }
  })
  // ...
],

Устранение мертвого кода Uglify затем удалит все это, поскольку обнаружит, что код, обернутый проверкой "production" !== "production", недоступен.

person Jonny Buchanan    schedule 23.07.2015
comment
Это тоже приятно знать, хотя, поскольку мой босс хочет использовать React из CDN, мы будем придерживаться этого пути. - person Andy; 24.07.2015