create-react-app는 src 디렉토리 외부로 제한을 가져옵니다.


150

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당신이 먼저 구성 요소 폴더에서 src 폴더 밖으로 두 번 올라갔습니다.
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/. 이 플러그인을 사용하면 앱의 소스 디렉토리에서 상대적인 가져 오기가 외부로 도달하지 않습니다.

ejectcreate-react-app 프로젝트를 실행 한 후에 만이 기능을 비활성화 할 수 있습니다 .

대부분의 기능과 업데이트는 create-react-app 시스템 내부에 숨겨져 있습니다. eject당신이 더 이상 일부 기능과 업데이트가 없습니다 만들 경우 . 따라서 웹팩 등을 구성하는 데 포함 된 응용 프로그램을 관리하고 구성 할 준비가되지 않은 경우 eject작업을 수행하지 마십시오 .

기존 규칙에 따라 재생합니다 (src로 이동). 그러나 이제 제한을 제거하는 방법을 알 수 있습니다 : webpack 구성 파일에서 do eject및 removeModuleScopePlugin .


이후 생성이-반응 - 응용 프로그램 v0.4.0NODE_PATH 환경 변수는 절대 수입 경로를 지정할 수 있습니다. 그리고 v3.0.0 NODE_PATH 은 or baseUrl에서 설정하기 위해 더 이상 사용되지 않습니다 .jsconfig.jsontsconfig.json

절대 가져 오기를 사용하면 기본 URL에 지정된 값을 기준으로 import App from 'App'대신 사용할 수 있습니다 import App from './App'.

이 기능은 monorepos 또는 기타 구성 질문에 특히 유용하지만 public폴더 에서 이미지 나 다른 것을 가져 오는 데는 유용하지 않습니다 .

public폴더의 내용은 폴더에 배치 build되고 상대 URL로 제공됩니다. 또한 가져온 모든 내용은 webpack에서 처리되며 build폴더 에도 저장됩니다.

public폴더 에서 무언가를 가져 오면 아마도 그 것이 폴더에 복제 build되고 두 가지 다른 URL (또는 다른로드 방법)로 사용 가능하게되어 궁극적으로 패키지 다운로드 크기가 악화됩니다.

src 폴더 에서 가져 오는 것이 바람직하며 장점이 있습니다. 모든 것은 웹팩에 의해 최적의 크기최적의 로딩 효율을 위해 덩어리로 번들에 포장 될 것입니다 .


중간 솔루션, 즉있다 재배 선에 프로그래밍 방식으로 웹팩 설정을 수정할 수 있습니다 시스템은. 그러나 플러그인을 제거 하는 것은 좋은 해결책 이 아닙니다 . 와 비슷한 완전히 작동하는 추가 디렉토리를 추가하는 것이 좋습니다 .ModuleScopePluginsrc

현재 루트 폴더 create-react-app이외의 추가 디렉토리는 지원하지 않습니다 src. 이것은 react-app-rewire-alias를 사용하여 수행 할 수 있습니다


3
./src 내에 symlink를 생성하고 거기에서 가져 오면 빌드가 작동하지 않습니다 (바벨 플러그인은 symlinked 폴더의 소스를 변환하지 않습니다). 따라서 src에 따라이 제한이 설정되고 심볼릭 링크가 없으면 '다른 프로젝트와 코드를 공유하지 않는'감옥에 효과적으로 배치됩니다 (CRA에서 완전히 이주 / 배출을 선택하지 않는 한)
VP

2
@VP이지만 "프로젝트의 node_modules /에서 심볼릭 링크를 추가하십시오"라는 오류가 표시됩니다. 작동하지 않습니까?
adrianmc

create-react-appwebpack 설정을 꺼내고 싶지 않은 사람들을 위해 실행할 때 이것을 비활성화하는 플래그를 만들어야합니다 . 개인적으로 나는 항상 꺼내지 만 일부 사람들은 편하게 구성하는 webpacks를 엉망으로 생각하지 않습니다.
TetraDev

2
@ 아드리안 많은 프로젝트가 node_modules가 아닌 공유 구성 요소 / 코드를 사용하기 때문에 프로젝트의 node_modules에서 symlink를 추가하면 작동하지 않습니다. 예를 들어 React Native와 React Native Web간에 코드를 공유합니다. 이 '스 니펫'은 node_modules가 아니며이 두 프로젝트는 실제로 다른 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')])and 만 사용 removeModuleScopePlugin()합니다.
ivosh

이 코드 스 니펫을 어디에 배치해야하는지 확인할 수 있습니까?
bijayshrestha

1
@bijayshrestha react-app-rewired 프로젝트의 readme 파일을 읽고 설정 방법을 설명합니다. 설정하는 동안 config-overrides.js코드를 넣을 수 있는 파일을 만듭니다 .
루카스 바흐

ModuleScopePlugin플러그인을 제거하는 것은 좋은 생각 이 아닙니다 . react-app-src
rewire

1
이 솔루션은 Typescript와 함께 작동합니까? TS와 함께 작동시킬 수 없습니다.
user3053247

27

다른 사람의 답변에 조금 더 많은 정보를 제공합니다. .png 파일을 사용자에게 전달하는 방법에 관한 두 가지 옵션이 있습니다. 파일 구조는 선택한 방법을 따라야합니다. 두 가지 옵션은 다음과 같습니다.

  1. import x from yreact-create-app와 함께 제공된 모듈 시스템 ( )을 사용하여 JS와 번들로 묶습니다. src폴더 안에 이미지를 넣습니다 .

  2. public폴더 에서 제공하고 노드가 파일을 제공하게하십시오. create-react-app에는 분명히 환경 변수가 있습니다 (예 :) <img src={process.env.PUBLIC_URL + '/img/logo.png'} />;. 즉, React 앱에서 참조 할 수는 있지만 일반적인 GET 요청에서 브라우저가 별도로 요청하여 노드를 통해 제공 할 수 있습니다.

출처 : 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 / 외부의 상대적 가져 오기는 지원되지 않습니다. '
Arkady

귀하의 답변은 정확한 IMO이지만 귀하가 경로에 대해 이야기하고 있다는 것을 분명히 <img src="...">
밝히지

1
이것은 내가 찾던 것입니다! CRA의 "src"디렉토리에 "images"폴더를 추가 한 다음 사용할 수있었습니다.<img src="/images/logo.png" alt="Logo" />
Amos Long

12

당신은 이동해야 WC-BlackonWhite.jpg당신에 src디렉토리. public디렉토리 (예 : 파비콘 등) HTML에 직접 연결되도록 당신이 번들로 직접 가져 오는 거라고, 아니 물건을거야 정적 파일입니다.


나는 다른 사람들이 이런 식으로하는 것을 보았다. 이것이 제가 이것이 올바른 방법이라고 생각한 이유
David Brierton

@DavidBrierton :이주의 사항은 최신 버전의 create-react-app에 추가되었을 수 있습니다.
Joe Clay

8

솔루션을 제공하는 몇 가지 답변이 react-app-rewired있지만 조금 더 우아한 customize-cra특수 removeModuleScopePlugin()API를 노출합니다 . (동일한 솔루션이지만 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

6

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에 투표하십시오! 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

추신 : eject 결과에주의하십시오 .


@SurajRao에게 감사드립니다. 나는 그것이 더 좋기를 바랍니다.
its4zahoor

@PattycakeJr 예, 아래에서 꺼내기 결과를 조심해야한다고 말한 것입니다.
its4zahoor

3

이 두 패키지를 설치

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

추출 할 필요가 없습니다 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 Extension 내에서 이미지 사용

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 design을 사용할 때 와 같이 여러 가지 수정이 필요한 경우 다음과 같은 여러 기능을 결합 할 수 있습니다.

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.