webentwicklung-frage-antwort-db.com.de

Die "create-react-app" -Importbeschränkung außerhalb des src-Verzeichnisses

Ich benutze die create-react-App. Ich versuche, ein Bild aus meinem öffentlichen Ordner aus einer Datei in meinem src/components Aufzurufen. Ich erhalte diese Fehlermeldung.

./src/components/website_index.js Modul nicht gefunden: Sie haben versucht, ../../public/images/logo/WC-BlackonWhite.jpg zu importieren, das außerhalb des Projektverzeichnisses src/liegt. Relative Importe außerhalb von src/werden nicht unterstützt. Sie können es entweder in src/verschieben oder einen Symlink von node_modules/des Projekts hinzufügen.

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

Ich habe viele Dinge gelesen, die besagen, dass Sie den Pfad importieren können, aber das funktioniert bei mir immer noch nicht. Jede Hilfe wäre sehr dankbar. Ich weiß, dass es so viele Fragen gibt, aber alle sagen mir, dass ich ein Logo oder ein Bild importieren soll, damit klar ist, dass mir etwas im großen Ganzen fehlt.

80
David Brierton

Dies ist eine spezielle Einschränkung, die von Entwicklern der create-react-app hinzugefügt wurde. Es ist in ModuleScopePlugin implementiert, um sicherzustellen, dass sich die Dateien in src/ Befinden. Dieses Plugin stellt sicher, dass relative Importe aus dem Quellverzeichnis der App nicht außerhalb desselben landen.

Sie können diese Funktion deaktivieren, jedoch erst, nachdem eject das Projekt "create-react-app" ausgeführt hat.

Die meisten Funktionen und Aktualisierungen sind in den Interna des Create-React-App-Systems verborgen. Wenn Sie eject machen, werden Sie einige Funktionen und deren Aktualisierung nicht mehr haben. Wenn Sie also nicht bereit sind, die zum Konfigurieren von Webpack usw. enthaltene Anwendung zu verwalten und zu konfigurieren, führen Sie keine eject -Operation aus.

Spiele nach den bestehenden Regeln (gehe zu src). Jetzt können Sie jedoch die Einschränkung entfernen: do eject und ModuleScopePlugin aus der Webpack-Konfigurationsdatei entfernen.


Da create-react-appv0.4. die Umgebungsvariable NODE_PATH Erlaubt, einen Pfad für den absoluten Import anzugeben.

Beim absoluten Import kann import App from 'App' Anstelle von import App from './App' Relativ zu dem in der Variablen NODE_PATH Angegebenen Wert verwendet werden.

Diese Funktion ist besonders nützlich für Monorepos oder andere Konfigurationsfragen, aber nicht zum Importieren von Bildern oder anderen Elementen aus dem Ordner public.

Der Inhalt des Ordners public wird im Ordner build abgelegt und ist über die relative URL verfügbar. Auch alles, was importiert wird, wird von webpack verarbeitet und auch in den Ordner build gestellt.

Wenn Sie etwas aus dem Ordner public importieren, wird dieses Element wahrscheinlich im Ordner build dupliziert und ist über zwei verschiedene URLs (oder mit unterschiedlichen Lademethoden) verfügbar, was letztendlich den Paketdownload verschlechtert Größe.

Importieren aus dem src Ordner ist günstiger und hat Vorteile. Alles wird per Webpack zum Bundle mit Brocken gepackt optimale Größe und für beste Ladeeffizienz.

76
oklas

Um ein bisschen mehr Informationen zu den Antworten anderer anzubieten. Sie haben zwei Möglichkeiten, wie Sie die PNG-Datei an den Benutzer übermitteln können. Die Dateistruktur sollte der von Ihnen gewählten Methode entsprechen. Die zwei Optionen sind:

  1. Verwenden Sie das Modulsystem (import x from y) zur Verfügung gestellt mit React-Create-App und bündeln Sie es mit Ihrem JS. Legen Sie das Bild in den Ordner src.

  2. Stellen Sie es aus dem Ordner public bereit und lassen Sie Node die Datei bereitstellen. Die create-react-app enthält anscheinend auch eine Umgebungsvariable, z. B. <img src={process.env.PUBLIC_URL + '/img/logo.png'} />;. Dies bedeutet, dass Sie in Ihrer React App darauf verweisen können, es aber weiterhin über Node bereitgestellt haben, wobei Ihr Browser dies in einer normalen GET-Anfrage separat anfordert.

Quelle: Erstellen-Reagieren-App

22
danielgormly

Mit dem Paket react-app-rewired kann das Plugin entfernt werden. Auf diese Weise müssen Sie nicht auswerfen.

Befolgen Sie die Schritte auf der Seite npm package (installieren Sie das Paket und kehren Sie die Aufrufe in der Datei package.json um) und verwenden Sie ein config-overrides.js Datei ähnlich dieser:

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;
};

Dadurch wird das ModuleScopePlugin aus den verwendeten WebPack-Plugins entfernt, der Rest bleibt jedoch unverändert, und das Auswerfen ist nicht mehr erforderlich.

17
Lukas Bach

Wenn sich Ihre Bilder im öffentlichen Ordner befinden, sollten Sie verwenden

"/images/logo_2016.png"

in deinem <img>src statt zu importieren

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

Das wird funktionieren

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

Sie müssen WC-BlackonWhite.jpg In Ihr src Verzeichnis verschieben. Das public -Verzeichnis ist für statische Dateien gedacht, die direkt im HTML-Code verlinkt werden (z. B. das Favicon), und nicht für Inhalte, die Sie direkt in Ihr Bundle importieren möchten.

10
Joe Clay

Diese Einschränkung stellt sicher, dass sich alle Dateien oder Module (Exporte) im Verzeichnis src/ Befinden. Die Implementierung erfolgt in ./node_modules/react-dev-utils/ModuleScopePlugin.js In den folgenden Codezeilen.

// 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();
      }

Sie können diese Einschränkung aufheben, indem Sie

  1. entweder diesen Code ändern (nicht empfohlen)
  2. oder mache eject und entferne dann ModuleScopePlugin.js aus dem Verzeichnis.
  3. oder kommentiere/entferne const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin'); von ./node_modules/react-scripts/config/webpack.config.dev.js

PS: Vorsicht vor den Folgen von Auswerfen .

4
its4zahoor

die beste Lösung ist es, react-scripts, dies wird tatsächlich in der offiziellen Dokumentation erwähnt, siehe: Alternativen zum Auswerfen

1

Wenn Sie nur eine einzelne Datei wie README.md oder package.json importieren müssen, kann diese explizit zu ModuleScopePlugin () hinzugefügt werden.

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()
      ]),
    ]
  }
}
1
James McGuigan

Sie müssen nicht auswerfen, Sie können das react-scripts config mit der rescripts library

Das würde dann funktionieren:

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

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

  return config;
};
1
Lukas