La creazione-reattiva-app importa le restrizioni al di fuori della directory src


151

Sto usando creare-reagire-app. Sto provando a chiamare un'immagine dalla mia cartella pubblica da un file all'interno del mio src/components. Ricevo questo messaggio di errore.

./src/components/website_index.js Modulo non trovato: hai tentato di importare ../../public/images/logo/WC-BlackonWhite.jpg che non rientra nella directory src / del progetto. Le importazioni relative al di fuori di src / non sono supportate. Puoi spostarlo all'interno di src / o aggiungere un link simbolico dal nodo_moduli del progetto /.

import logo from '../../public/images/logo_2016.png'; <img className="Header-logo" src={logo} alt="Logo" />

Ho letto molte cose dicendo che puoi fare un'importazione nel percorso ma che non funziona ancora per me. Qualsiasi aiuto sarebbe molto apprezzato. So che ci sono molte domande come questa, ma tutte mi stanno dicendo di importare il logo o l'immagine così chiaramente che mi manca qualcosa nel quadro generale.


2
È necessario ../public/images/logo_2016.pngSei salito due volte, prima fuori dalla cartella dei componenti, quindi dalla cartella src.
Chris G,

./src/components/website_index.js Modulo non trovato: hai tentato di importare ../../public/images/logo/WC-BlackonWhite.jpg che non rientra nella directory src / del progetto. Le importazioni relative al di fuori di src / non sono supportate. Puoi spostarlo all'interno di src / o aggiungere un link simbolico dal nodo_moduli del progetto /.
David Brierton,

Il mio commento presuppone che la publiccartella sia direttamente all'interno della srccartella. Il tuo commento senza commenti presenta il vecchio percorso che inizia con ../..quindi non sei sicuro di quale sia il tuo punto?
Chris G,

3
nessun pubblico è allo stesso livello di src
David Brierton,

Che cosa significano per "o aggiungere un link simbolico ad esso da node_modules /" del progetto?
Julha,

Risposte:


128

Questa è una restrizione speciale aggiunta dagli sviluppatori di create -eagire-app. È implementato ModuleScopePluginper garantire che i file risiedano in src/. Tale plug-in garantisce che le importazioni relative dalla directory di origine dell'app non raggiungano al di fuori di essa.

È possibile disabilitare questa funzione ma solo dopo l' ejectoperazione del progetto create -eagire-app.

La maggior parte delle funzionalità e dei suoi aggiornamenti sono nascosti all'interno del sistema create -eagire-app. Se lo fai ejectnon avrai più alcune funzionalità e il suo aggiornamento. Pertanto, se non si è pronti a gestire e configurare l'applicazione inclusa per configurare il webpack e così via, non eseguire ejectoperazioni.

Gioca secondo le regole esistenti (passa a SRC). Ma ora si può sapere come rimuovere restrizione: fare ejecte rimuovere ModuleScopePlugindal file di configurazione webpack .


Dal momento che create -eagire -app v0.4.0 la NODE_PATHvariabile di ambiente consente di specificare un percorso per l'importazione assoluta. E poiché v3.0.0 NODE_PATH è deprecato a favore dell'impostazione baseUrlin jsconfig.jsono tsconfig.json.

L'importazione assoluta consente l'utilizzo import App from 'App'invece import App from './App'rispetto al valore specificato nell'URL di base.

Questa funzione è particolarmente utile per i monorepos o altre domande di configurazione ma non per l'importazione di immagini o altro dalla publiccartella.

Il contenuto della publiccartella verrà inserito nella buildcartella e disponibile tramite l'URL relativo. Inoltre, tutto ciò che viene importato verrà elaborato dal webpack e verrà inserito anche nella buildcartella.

Se importi qualcosa dalla publiccartella, probabilmente quell'elemento verrà duplicato nella buildcartella e sarà disponibile con due URL diversi (o con modi diversi di caricare), che alla fine peggioreranno le dimensioni del download del pacchetto.

È preferibile importare dalla cartella src e presenta vantaggi. Tutto sarà imballato dal webpack in bundle con pezzi di dimensioni ottimali e per la migliore efficienza di caricamento .


Esistono soluzioni intermedie, vale a dire il sistema rewire che consente di modificare a livello di programmazione la configurazione del webpack. Ma rimuovere il ModuleScopePluginplugin non è una buona soluzione; è meglio aggiungere directory aggiuntive perfettamente funzionanti simili a src.

Attualmente, create-react-appnon supporta directory aggiuntive se non srcnella cartella principale. Questo può essere fatto usando alias reatt-app-rewire-alias


3
se si crea un collegamento simbolico all'interno di ./src e si importa da lì - la build non funziona (il plugin babel non trasforma i sorgenti in cartelle con collegamenti simbolici). Quindi, con questa restrizione, on e no-symlink sotto src, sei effettivamente collocato in una prigione "no-sharing-code-with-other-projects" (a meno che tu scelga di emigrare / espellere completamente dalla CRA)
VP

2
@VP ma l'errore dice "aggiungi un link simbolico dal nodo_moduli /." Del progetto, non funziona?
Adrianmc,

Dovrebbero creare un flag per disabilitarlo quando sono in esecuzione create-react-appper coloro che non vogliono espellere la configurazione del webpack. Personalmente esplodo sempre, ma alcune persone non si sentono ancora a proprio agio con i webpack confortabili.
TetraDev,

2
@adrianmc. l'aggiunta del collegamento simbolico dai nodi_moduli del progetto non funziona, poiché molti progetti utilizzano componenti / codice di condivisione che non sono nodi_moduli. Ad esempio, condivido il codice tra React Native e React native web. Quei "frammenti" non sono node_modules e questi 2 progetti in realtà hanno differenti node_modules.
VP

1
Come è questa la risposta accettata? Questa restrizione fasulla è banalmente eliminata semplicemente impostando NODE_PATH=./src/..nel .envfile. In questo modo, puoi importare dall'esterno della cartella src senza passare attraverso il dolore associato all'espulsione della tua app.
Flaom

47

Il pacchetto reatt-app-ricablato può essere usato per rimuovere il plugin. In questo modo non è necessario espellere.

Seguire i passaggi nella pagina del pacchetto npm (installare il pacchetto e invertire le chiamate nel file package.json) e utilizzare un config-overrides.jsfile simile a questo:

const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');

module.exports = function override(config, env) {
    config.resolve.plugins = config.resolve.plugins.filter(plugin => !(plugin instanceof ModuleScopePlugin));

    return config;
};

Questo rimuoverà ModuleScopePlugin dai plugin WebPack usati, ma lascerà il resto com'era e rimuoverà la necessità di espellere.


5
Bella risposta. Puoi sfruttare ulteriormente react-app-rewiredcon [ github.com/arackaf/customize-cra lasting ( customize - cra) . Quindi la configurazione utilizzerà solo babelInclude([path.resolve('src'), path.resolve('../common')])e removeModuleScopePlugin().
Ivosh

puoi confermare dove devo inserire questo frammento di codice?
bijayshrestha,

1
@bijayshrestha Leggi il file Leggimi del progetto rea-app-ricablato, lì spiega come impostarlo. Durante l'installazione, creerai un config-overrides.jsfile in cui puoi inserire il codice.
Lukas Bach,

Rimuovere il ModuleScopePluginplugin non è una buona idea. È meglio aggiungere ulteriori directory completamente funzionanti simili srcall'utilizzo di reagire-app-rewire-alias
oklas

1
Questa soluzione funziona con Typescript? Non riesco a farlo funzionare con TS.
user3053247

27

Per offrire un po 'più di informazioni alle risposte degli altri. Hai due opzioni su come consegnare il file .png all'utente. La struttura del file deve essere conforme al metodo scelto. Le due opzioni sono:

  1. Utilizzare il sistema del modulo ( import x from y) fornito con React-create-app e raggrupparlo con JS. Posiziona l'immagine all'interno della srccartella.

  2. Servilo dalla publiccartella e lascia che Node serva il file. Apparentemente, create -eagire-app include anche una variabile d'ambiente, ad es <img src={process.env.PUBLIC_URL + '/img/logo.png'} />;. Ciò significa che puoi fare riferimento nella tua app React ma averlo ancora servito tramite Node, con il tuo browser che lo richiede separatamente in una normale richiesta GET.

Fonte: create -eagire-app


Il suggerimento n. 2 è esattamente ciò che causa il seguente errore per me: Modulo non trovato: Hai tentato di importare ./../../../public/CheersBar-Drinks-147.jpg che non rientra nella directory src / del progetto . Le importazioni relative al di fuori di src / non sono supportate. Puoi spostarlo all'interno di src / o aggiungere un link simbolico dal nodo_moduli del progetto /.
Amos Long,

25

Se le tue immagini sono nella cartella pubblica, allora dovresti usare

"/images/logo_2016.png"

nel tuo <img> srcinvece di importare

'../../public/images/logo_2016.png'; 

Questo funzionerà

<img className="Header-logo" src="/images/logo_2016.png" alt="Logo" />

2
Non funziona per me. Ottenere lo stesso messaggio - 'al di fuori della directory src / del progetto. Le importazioni relative al di fuori di SRC / non sono supportate. "
Arkady,

La tua risposta è corretta IMO ma mi sono preso la libertà di chiarire che stai parlando del percorso <img src="...">, non importandolo
Dmitry Yudakov

1
Questo era esattamente quello che stavo cercando! Ho semplicemente aggiunto una cartella "images" alla directory "src" della mia CRA, e poi sono stato in grado di usare<img src="/images/logo.png" alt="Logo" />
Amos Long

12

Devi spostarti WC-BlackonWhite.jpgnella tua srcdirectory. La publicdirectory è per i file statici che verranno collegati direttamente nell'HTML (come favicon), non cose che importerai direttamente nel tuo bundle.


Ho visto gli altri farlo in questo modo. Ecco perché ho pensato che fosse il modo giusto
David Brierton,

@DavidBrierton: questa precauzione potrebbe essere stata aggiunta in una versione più recente di create -eagire-app.
Joe Clay,

8

Ci sono alcune risposte che forniscono soluzioni react-app-rewired, ma customize-craespongono removeModuleScopePlugin()un'API speciale che è un po 'più elegante. (È la stessa soluzione, ma sottratta al customize-crapacchetto.)

npm i --save-dev react-app-rewired customize-cra

package.json

"scripts": {
    - "start": "react-scripts start"
    + "start": "react-app-rewired start",
    ...
},

config-overrides.js

const { removeModuleScopePlugin } = require('customize-cra')

module.exports = removeModuleScopePlugin()

1
mi hai salvato la giornata!
lmiguelvargasf

6

Rimuovilo usando Craco:

module.exports = {
  webpack: {
    configure: webpackConfig => {
      const scopePluginIndex = webpackConfig.resolve.plugins.findIndex(
        ({ constructor }) => constructor && constructor.name === 'ModuleScopePlugin'
      );

      webpackConfig.resolve.plugins.splice(scopePluginIndex, 1);
      return webpackConfig;
    }
  }
};

Vota il craco! Craco supporta CRA 3.x
Roman Podlinov

4

Questa restrizione assicura che tutti i file o moduli (esportazioni) si trovino all'interno della src/directory, l'implementazione è in ./node_modules/react-dev-utils/ModuleScopePlugin.js, nelle seguenti righe di codice.

// Resolve the issuer from our appSrc and make sure it's one of our files
// Maybe an indexOf === 0 would be better?
     const relative = path.relative(appSrc, request.context.issuer);
// If it's not in src/ or a subdirectory, not our request!
     if (relative.startsWith('../') || relative.startsWith('..\\')) {
        return callback();
      }

È possibile rimuovere questa restrizione da

  1. o cambiando questo pezzo di codice (non raccomandato)
  2. o noneject rimuovere ModuleScopePlugin.jsdalla directory.
  3. o commentare / rimuovere const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');da./node_modules/react-scripts/config/webpack.config.dev.js

PS: attenzione delle conseguenze di espulsione .


Grazie @SurajRao, l'ho spostato qui. Spero sia meglio
its4zahoor,

@PattycakeJr Sì, ecco perché di seguito ho detto di essere al corrente delle conseguenze di espulsione.
its4zahoor,

3

installa questi due pacchetti

npm i --save-dev react-app-rewired customize-cra

package.json

"scripts": {
    - "start": "react-scripts start"
    + "start": "react-app-rewired start"
},

config-overrides.js

const { removeModuleScopePlugin } = require('customize-cra');

module.exports = function override(config, env) {
    if (!config.plugins) {
        config.plugins = [];
    }
    removeModuleScopePlugin()(config);

    return config;
};

2

Non è necessario espellere, è possibile modificare la react-scriptsconfigurazione con la libreria di script

Questo funzionerebbe quindi:

module.exports = config => {
  const scopePluginIndex = config.resolve.plugins.findIndex(
    ({ constructor }) => constructor && constructor.name === "ModuleScopePlugin"
  );

  config.resolve.plugins.splice(scopePluginIndex, 1);

  return config;
};

2

Penso che la soluzione di Lukas Bach per utilizzare la reatt-app-ricablata al fine di modificare la configurazione del webpack sia un buon modo di procedere, tuttavia, non escluderei l'intero ModuleScopePlugin ma invece autorizzo il file specifico che può essere importato al di fuori di src:

config-overrides.js

const ModuleScopePlugin = require("react-dev-utils/ModuleScopePlugin");
const path = require("path");

module.exports = function override(config) {
  config.resolve.plugins.forEach(plugin => {
    if (plugin instanceof ModuleScopePlugin) {
      plugin.allowedFiles.add(path.resolve("./config.json"));
    }
  });

  return config;
};

Questa è la soluzione migliore finora.
adi518,

2

Immagine all'interno della cartella pubblica

  use image inside html extension
  <img src="%PUBLIC_URL%/resumepic.png"/>

  use image inside  js extension
  <img src={process.env.PUBLIC_URL+"/resumepic.png"}/>
  • usa l'immagine all'interno dell'estensione js

1

Se devi solo importare un singolo file, come README.md o package.json, questo può essere aggiunto esplicitamente a ModuleScopePlugin ()

config / paths.js

const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
module.exports = {
  appPackageJson: resolveApp('package.json'),
  appReadmeMD:    resolveApp('README.md'),
};

config / webpack.config.dev.js + config / webpack.config.prod.js

module.exports = {
  resolve: {
    plugins: [
      // Prevents users from importing files from outside of src/ (or node_modules/).
      // This often causes confusion because we only process files within src/ with babel.
      // To fix this, we prevent you from importing files out of src/ -- if you'd like to,
      // please link the files into your node_modules/ and let module-resolution kick in.
      // Make sure your source files are compiled, as they will not be processed in any way.
      new ModuleScopePlugin(paths.appSrc, [
          paths.appPackageJson,
          paths.appReadmeMD         // README.md lives outside of ./src/ so needs to be explicitly included in ModuleScopePlugin()
      ]),
    ]
  }
}

3
Ciò richiede la prima espulsione dall'app create-reply-app, no?
Beau Smith,


1

Se hai bisogno di più modifiche, come quando usi la progettazione di formiche , puoi combinare più funzioni come questa:

const {
  override,
  removeModuleScopePlugin,
  fixBabelImports,
} = require('customize-cra');

module.exports = override(
  fixBabelImports('import', {
    libraryName: 'antd',
    libraryDirectory: 'es',
    style: 'css',
  }),
  removeModuleScopePlugin(),
);

1

Aggiungendo alla risposta di Bartek Maciejiczek, ecco come appare con Craco:

const ModuleScopePlugin = require("react-dev-utils/ModuleScopePlugin");
const path = require("path");

module.exports = {
  webpack: {
    configure: webpackConfig => {
      webpackConfig.resolve.plugins.forEach(plugin => {
        if (plugin instanceof ModuleScopePlugin) {
          plugin.allowedFiles.add(path.resolve("./config.json"));
        }
      });
      return webpackConfig;
    }
  }
};

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.