Динамический импорт с не связанным файлом

У меня есть проект React в комплекте с Webpack.

У меня есть компонент, который я хочу, чтобы он отображал компоненты динамически. В моем случае путь компонента происходит от реквизита.

Кроме того, эти компоненты не включены в файл моего проекта.js; они являются внешними компонентами / библиотеками React.

Я пробовал импорт Dynamic ES6:

componentWillReceiveProps(nextProps){
    if(nextProps.pagesData && this.props.pagesData !== nextProps.pagesData && nextProps.pagesData.get('cards').count() > 0){

        // Getting the first card from the Immutable object
        let card = nextProps.pagesData.getIn(['cards', 0]);

        // Getting the cardType which can be: '/path/index.js'
        let cardType = card.get('card_type');

        // ES6 Dynamic import
        import(cardType)
            .then(module => {
                 this.setState({ asyncCard: module.default });
             })
    }
}

Это не работает, потому что для импорта нужен статический маршрут.

Затем я попытался с помощью:

let dynamicComponent = require(cardType);

Что не работает, потому что (я предполагаю) Webpack пытается найти его в основной комплект.

Это вообще возможно сделать?

Обновление: похоже, это может работать (cardType - это index.js - компонент React):

import(`/home/user/_apps/module/react-module/lib/${cardType}`)

Webpack создает другой пакет (чанк), включая код index.js и все его зависимости.

Но это не решает мой первоначальный вопрос.

Редактирование 2: импорт сверху фактически игнорирует последнюю переменную, а Webpack создает фрагменты каждого файла внутри /lib.

1 ответ

Решение

Я наконец-то придумал решение.

Библиотека LoadJS. Вы также можете использовать $script.

Проект библиотеки (внешние компоненты): index.js:

import App from './App';

export const MyComponentLib = {
   App
};

App.jsx:

import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

export default class App extends Component {
   render() {
      return (
         <div className="App">
             <header className="App-header">
                 <img src={logo} className="App-logo" alt="logo" />
                 <h1 className="App-title">Welcome to React</h1>
             </header>
             <p className="App-intro">
                 To get started, edit <code>src/App.js</code> and save to reload.
             </p>
         </div>
      );
   }
}

В конфигурационный файл веб-пакета библиотеки (производство) добавлено:

libraryTarget: 'umd',

Основной файл проекта (main.js):

componentWillReceiveProps(nextProps){
    if(nextProps.pagesData && this.props.pagesData !== nextProps.pagesData && nextProps.pagesData.get('cards').count() > 0){

        // Getting all asyncCards from state
        let currentCards = cloneDeep(this.state.asyncCards);

        // Immutable "get" function - getting cards from nextProps
        nextProps.pagesData.get('cards').forEach(card => {

            // Getting card_type, which in this case is the filename
            let cardType = card.get('card_type');

            // Do we have this card already in the state object?
            if(!hasIn(currentCards, cardType)) {

                // AsyncLoading the card file
                loadjs(`/custom/1/${cardType}.js`, cardType, {
                    success: () => {

                        // Cloning App function (the component)
                        currentCards[cardType] = window.MyComponentLib.App.bind({});

                        this.setState({
                            asyncCards: currentCards
                        })
                    }
                })
            }
        })
    }
}
Другие вопросы по тегам