create-react-appがsrcディレクトリの外部にインポート制限をインポートする


149

私はcreate-react-appを使用しています。内のファイルからパブリックフォルダーの画像を呼び出そうとしていますsrc/components。このエラーメッセージが表示されます。

./src/components/website_index.jsモジュールが見つかりません:プロジェクトのsrc /ディレクトリの外にある../../public/images/logo/WC-BlackonWhite.jpgをインポートしようとしました。src /以外の相対インポートはサポートされていません。src /内に移動するか、プロジェクトのnode_modules /からシンボリックリンクを追加できます。

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

パスへのインポートを実行できると多くのことを読みましたが、それでもまだ機能しません。どんな助けでも大歓迎です。このような質問がたくさんあることは知っていますが、ロゴや画像をインポートするように言われているので、全体像で何かが欠けています。


2
../public/images/logo_2016.png最初にcomponentsフォルダーから、次にsrcフォルダーから、2回上がった必要があります。
Chris G

./src/components/website_index.jsモジュールが見つかりません:プロジェクトのsrc /ディレクトリの外にある../../public/images/logo/WC-BlackonWhite.jpgをインポートしようとしました。src /以外の相対インポートはサポートされていません。src /内に移動するか、プロジェクトのnode_modules /からシンボリックリンクを追加できます。
David Brierton

私のコメントは、あなたのpublicフォルダが直接あなたのフォルダの中にあると仮定していsrcます。あなたのコメントのないコメントは古いパスから始まっている../..ので、あなたのポイントが何であるかわかりませんか?
Chris G

3
srcと同じレベルのパブリックはありません
David Brierton

「またはプロジェクトのnode_modules /からシンボリックリンクを追加する」とはどういう意味ですか?
Julha

回答:


127

これは、create-react-appの開発者によって追加された特別な制限です。に実装されModuleScopePlugin、ファイルが確実にに常駐しsrc/ます。このプラグインは、アプリのソースディレクトリからの相対インポートがその外部に到達しないようにします。

この機能ejectは、create-react-appプロジェクトの操作後にのみ無効にできます。

ほとんどの機能とその更新は、create-react-appシステムの内部に隠されています。作成ejectすると、いくつかの機能とその更新がなくなります。したがって、webpackなどの設定に含まれるアプリケーションを管理および設定する準備ができていない場合は、eject操作しないでください。

既存のルールでプレイします(srcに移動)。しかし今、あなたは制限を取り除く方法を知ることができます:実行してwebpack設定ファイルからeject削除ModuleScopePluginしてください


以来作成反応するアプリ v0.4.0NODE_PATH環境変数絶対インポートのパスを指定することを可能にします。また、v3.0.0 NODE_PATHは非推奨となっているためbaseUrljsconfig.jsonまたはでの設定が推奨されtsconfig.jsonます。

絶対インポートでは、ベースURLで指定された値を基準にしてimport App from 'App'代わりに使用できますimport App from './App'

この機能は、monoreposまたはその他の構成に関する質問に特に役立ちますが、publicフォルダーから画像やその他のものをインポートする場合には役立ちません。

publicフォルダーのコンテンツはフォルダーに配置されbuild、相対URLで使用できます。また、インポートされたものはすべてwebpackによって処理され、buildフォルダーにも配置されます。

publicフォルダーから何かをインポートすると、おそらくそのものがbuildフォルダーに複製され、2つの異なるURL(または異なるロード方法)で使用できるようになるため、最終的にパッケージのダウンロードサイズが悪化します。

srcフォルダーからインポートすることをお勧めします。すべては、最適なサイズのチャンクで、最高のロード効率のために、Webpackによってバンドルにパックされます


中間ソリューション、すなわち存在するのReWireあなたは、プログラムのWebPACKの設定を変更することを可能にするシステムが。しかし、プラグインを削除すること良い解決策ではありません。と同様に、完全に機能する追加のディレクトリを追加することをお勧めします。ModuleScopePluginsrc

現在、 create-react-appsrcルートフォルダー以外の追加のディレクトリはサポートされていません。これは、react-app-rewire-aliasを使用して実行できます。


3
./src内にシンボリックリンクを作成し、そこからインポートする場合、ビルドは機能しません(babelプラグインはシンボリックリンクフォルダーのソースを変換しません)。したがって、この制限により、srcの下のシンボリックリンクがない場合、「CRAから完全に移行/イジェクトすることを選択しない限り)実質的に「no-sharing-code-with-other-projects」の刑務所に置かれます
VP

2
@VPですが、「プロジェクトのnode_modules /からシンボリックリンクを追加する」というエラーが表示されますが、これは機能しませんか?
adrianmc 2018

彼らは実行時にcreate-react-appwebpack設定をイジェクトしたくない人のためにこれを無効にするフラグを立てるべきです。個人的に私は常にイジェクトしますが、一部の人々は快適ではないが、webpackの厄介な設定をいじっています。
TetraDev 2018

2
@adrianmc。多くのプロジェクトがnode_modulesではない共有コンポーネント/コードを使用するため、プロジェクトのnode_modulesからシンボリックリンクを追加することはできません。たとえば、React NativeとReact Native Webの間でコードを共有しています。これらの「スニペット」はnode_modulesではなく、これらの2つのプロジェクトには実際には異なるnode_modulesがあります。
VP

1
これはどのように受け入れられた答えですか?この偽の制限はNODE_PATH=./src/...envファイルに設定するだけで簡単に解消されます。そうすることで、アプリのイジェクトに伴う問題を経験することなく、srcフォルダーの外部からインポートできます。
Flaom

47

パッケージreact-app-rewiredを使用してプラグインを削除できます。この方法では、イジェクトする必要はありません。

npmパッケージページの手順に従って(パッケージをインストールし、package.jsonファイルで呼び出しをフリップします)、次のようなconfig-overrides.jsファイルを使用します。

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

これにより、使用されているWebPackプラグインからModuleScopePluginが削除されますが、残りはそのままにして、取り出す必要がなくなります。


5
すばらしい答えです。react-app-rewired[ github.com/arackaf/customize-cra](customize-cra)でさらに活用できます。その後、構成はちょうどbabelInclude([path.resolve('src'), path.resolve('../common')])とを使用しremoveModuleScopePlugin()ます。
ivosh

このコードスニペットをどこに配置すればよいですか?
bijayshrestha

1
@bijayshrestha react-app-rewiredプロジェクトのreadmeファイルを読み、そこでセットアップ方法を説明します。セットアップ中にconfig-overrides.js、コードを配置できるファイルを作成します。
Lukas Bach、

ModuleScopePluginプラグインを削除することは良い考えではありませんreact-app-src
rewire

1
このソリューションはTypescriptで動作しますか?TSでは動作しません。
user3053247

27

他の人の答えにもう少し情報を提供するため。.pngファイルをユーザーに配信する方法については、2つのオプションがあります。ファイル構造は、選択した方法に準拠している必要があります。2つのオプションは次のとおりです。

  1. import x from yreact-create-appで提供されるモジュールシステム()を使用して、JSにバンドルします。srcフォルダ内に画像を配置します。

  2. それをpublicフォルダーから提供し、Nodeにファイルを提供させます。create-react-appには、環境変数も含まれているようです<img src={process.env.PUBLIC_URL + '/img/logo.png'} />;。これは、Reactアプリでそれを参照することはできますが、通常のGETリクエストでブラウザーが個別に要求することで、Nodeを通じてサービスを提供することを意味します。

ソース:create-react-app


提案#2は、私に次のエラーを引き起こすものです。モジュールが見つかりません:プロジェクトのsrc /ディレクトリーの外にある./../../../public/CheersBar-Drinks-147.jpgをインポートしようとしました。src /以外の相対インポートはサポートされていません。src /内に移動するか、プロジェクトのnode_modules /からシンボリックリンクを追加できます。
Amos Long

25

画像がパブリックフォルダーにある場合は、

"/images/logo_2016.png"

<img> srcインポートする代わりに

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

これは動作します

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

2
私のために働いていません。同じメッセージを取得する-'プロジェクトのsrc /ディレクトリの外。src /以外の相対インポートはサポートされていません。
アルカディ

あなたの答えは正解のIMOですが<img src="...">、インポートではなく、でパスについて話していることを明確にするために自由を取りました
Dmitry Yudakov

1
これはまさに私が探していたものでした!CRAの「src」ディレクトリに「images」フォルダを追加するだけで、使用できるようになりました<img src="/images/logo.png" alt="Logo" />
Amos Long

12

ディレクトリに移動する必要がありWC-BlackonWhite.jpgますsrcpublicディレクトリは、あなたのバンドルに直接インポートしようとしていること(例えばファビコンなど)HTMLに直接リンクすることになるだろう静的ファイル、ではないもののためです。


他の人がそれをこのようにするのを見てきました。だから私はこれが適切な方法だと思った
David Brierton

@DavidBrierton:この予防措置は、create-react-appの最新バージョンに追加された可能性があります。
Joe Clay

8

でソリューションを提供する回答がいくつかありますが、少しエレガントな特別なAPI react-app-rewiredcustomize-cra公開されていremoveModuleScopePlugin()ます。(同じソリューションですが、customize-craパッケージによって抽象化されています。)

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
あなたは私の日を救った!
lmiguelvargasf

5

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

クラコに投票!CracoはCRA 3.xをサポートしています
Roman Podlinov

4

この制限により、次のコード行でsrc/は、すべてのファイルまたはモジュール(エクスポート)がディレクトリ内にあり、実装はに./node_modules/react-dev-utils/ModuleScopePlugin.jsあります。

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

この制限を解除するには、

  1. このコードを変更するか(推奨されません)
  2. あるいはejectその後、削除ModuleScopePlugin.jsディレクトリから。
  3. やコメント/削除const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');から./node_modules/react-scripts/config/webpack.config.dev.js

PS:イジェクトの結果に注意してください。


@SurajRaoに感謝します。ここに移動しました。私はそれがより良いことを望みます。
its4zahoor 2018年

@PattycakeJrはい、そのため、以下でイジェクトの結果に注意するように言いました。
its4zahoor

3

これら2つのパッケージをインストールする

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

イジェクトする必要はありません。rescriptsライブラリでreact-scripts設定を変更できます

これはその後機能します:

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

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

  return config;
};

2

Webpack設定を変更するためにreact-app-rewiredを使用するLukas Bachソリューションは良い方法だと思いますが、ModuleScopePlugin全体を除外しませんなく、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;
};

これが今のところ最良の解決策です。
adi518

2

パブリックフォルダー内の画像

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

  use image inside  js extension
  <img src={process.env.PUBLIC_URL+"/resumepic.png"}/>
  • js拡張機能内で画像を使用する

1

README.mdやpackage.jsonなどの単一のファイルのみをインポートする必要がある場合、これを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
最初にcreate-react-appから排出する必要がありますか?
Beau Smith


1

Antデザインを使用する場合など複数の変更が必要な場合は、次のよう複数の機能を組み合わせることができます。

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

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

1

Bartek Maciejiczekの答えに加えて、これは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;
    }
  }
};

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.