Create-reakt-uygulaması kısıtlamayı src dizininin dışına aktarır


150

Ben create-tepki-app kullanıyorum. İçimdeki bir dosyadan ortak klasörümdeki bir görüntüyü çağırmaya çalışıyorum src/components. Bu hata iletisini alıyorum.

./src/components/website_index.js Modülü bulunamadı: Proje src / dizininin dışında kalan ../../public/images/logo/WC-BlackonWhite.jpg dosyasını içe aktarmaya çalıştınız. Src / dışındaki göreli ithalatlar desteklenmez. Src / içine taşıyabilir veya projenin node_modules / dizininden bir sembolik bağlantı ekleyebilirsiniz.

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

Yola bir ithalat yapabileceğinizi söyleyen birçok şey okudum ama bu hala benim için çalışmıyor. Herhangi bir yardım büyük mutluluk duyacağız. Bunun gibi birçok soru olduğunu biliyorum ama hepsi logo veya resmi ithal etmemi söylüyorlar. Büyük resimde bir şey eksik.


2
Gerekenler ../public/images/logo_2016.pngÖnce bileşenler klasöründen, sonra src klasöründen iki kez çıktınız.
Chris G

./src/components/website_index.js Modülü bulunamadı: Proje src / dizininin dışında kalan ../../public/images/logo/WC-BlackonWhite.jpg dosyasını içe aktarmaya çalıştınız. Src / dışındaki göreli ithalatlar desteklenmez. Src / içine taşıyabilir veya projenin node_modules / dizininden bir sembolik bağlantı ekleyebilirsiniz.
David Brierton

Yorumum, publicklasörünüzün doğrudan srcklasörün içinde olduğunu varsayar . Yorumsuz yorumunuz eski yolla başlıyor, ../..bu yüzden amacınızın ne olduğundan emin değil misiniz?
Chris G

3
src ile aynı seviyede hiçbir kamuoyu yok
David Brierton

Ne demek istiyorsun "ya da projenin node_modules / dizininden bir sembolik link ekle?"
Julha

Yanıtlar:


127

Bu, create-tepki uygulaması geliştiricileri tarafından eklenen özel bir kısıtlamadır. İçinde ModuleScopePlugindosyaların bulunmasını sağlamak için uygulanır src/. Bu eklenti, uygulamanın kaynak dizininden göreli içe aktarmaların onun dışına ulaşmamasını sağlar.

Bu özelliği ancak ejectoluştur-tepki uygulaması projesinin çalıştırılmasından sonra devre dışı bırakabilirsiniz .

Çoğu özellik ve güncellemeleri, oluştur-tepki-uygulama sisteminin içlerine gizlenmiştir. Bunu yaparsanız eject, artık bazı özelliklere ve güncellemesine sahip olmayacaksınız. Bu nedenle, web paketini yapılandırmak için dahil olan uygulamayı yönetmeye ve yapılandırmaya hazır değilseniz, ejectişlem yapmayın .

Mevcut kurallara göre oynayın (src'ye geçin). Ama şimdi kısıtlamayı kaldırmak için nasıl bilebilir: do ejectve kaldırmak ModuleScopePluginwebpack yapılandırma dosyasından .


Yana create-tepki-app v0.4.0NODE_PATH ortam değişkeni mutlak ithalat için bir yol belirlemenizi sağlar. Ve bu yana V3.0.0 NODE_PATH ayar lehine kullanımdan kaldırılmıştır baseUrlbölgesi jsconfig.jsonveya tsconfig.json.

Mutlak içe aktarma import App from 'App'bunun yerine kullanımına izin veririmport App from './App' temel url'de belirtilen değere göre .

Bu özellik özellikle monorepos veya diğer yapılandırma soruları için kullanışlıdır, ancak görüntüleri veya public klasörden .

publicKlasörün içeriği klasöre yerleştirilir buildve göreli URL tarafından kullanılabilir. Ayrıca, içe aktarılan her şey webpack tarafından işlenecek ve ayrıcabuild klasöre .

publicKlasörden bir şey içe aktarırsanız, muhtemelen bu şey klasörde çoğaltılır buildve sonuçta paket indirme boyutunu kötüleştiren iki farklı url (veya yükleme için farklı yollarla) tarafından kullanılabilir.

Src klasöründen içe aktarma tercih edilir ve avantajları vardır. Her şey webpack tarafından en uygun boyutta ve en iyi yükleme verimliliği için pakete paketlenecektir .


Ara çözümler, yani webpack yapılandırmasını programlı olarak değiştirmenize izin veren rewire sistemi vardır. Ama çıkarmadanModuleScopePlugin eklenti iyi değil çözüm; benzer şekilde tam olarak çalışan ek dizinler eklemek daha iyidir src.

Şu anda, kök klasör create-react-appdışındaki ek dizinleri desteklememektedir src. Bu, tepki-app-rewire-diğer adı kullanılarak yapılabilir


3
./src içinde symlink oluşturursanız ve oradan içe aktarırsanız - yapı çalışmaz (babel eklentisi, sembolik klasörlerde kaynakları dönüştürmez). Bu nedenle, src altında açık ve symlink olmadan, etkili bir 'diğer projelerle paylaşım kodu yok' hapishanesine yerleştirilirsiniz (CRA'dan tamamen göç etmeyi / çıkarmayı seçmediğiniz sürece)
VP

2
@VP ancak hata "projenin node_modules / dizininden bir sembolik bağlantı ekle" diyor, bu çalışmıyor mu?
adrianmc

create-react-appWebpack yapılandırmasını çıkarmak istemeyenler için çalıştırırken bunu devre dışı bırakmak için bir bayrak yapmalıdırlar. Şahsen ben her zaman çıkarıyorum, ama bazı insanlar henüz webpacks yıldırıcı yapılandırma ile uğraşmak rahat hissetmiyorum.
TetraDev

2
@adrianmc. projenin node_modules öğesinden symlink eklemek işe yaramaz, çünkü birçok proje node_modules olmayan paylaşım bileşenlerini / kodunu kullanır. Örneğin, React Native ve React native web arasında kod paylaşıyorum. Bu 'snippet'ler' node_modules değildir ve bu 2 projenin aslında farklı node_modules vardır.
VP

1
Kabul edilen cevap nasıl? Bu sahte kısıtlama trivially basitçe ayarlayarak ortadan NODE_PATH=./src/..içinde .envdosyanın. Bunu yaparak, uygulamanızı çıkarmayla ilgili acıyı yaşamadan src klasörünün dışından içe aktarabilirsiniz.
Flaom

47

Tepki-app-rewired paketi eklentiyi kaldırmak için kullanılabilir. Bu şekilde çıkarmanız gerekmez.

Npm paket sayfasındaki adımları izleyin (paketi kurun ve çağrıları package.json dosyasında çevirin) ve config-overrides.jsbuna benzer bir dosya kullanın :

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

Bu, ModuleScopePlugin'i kullanılan WebPack eklentilerinden kaldıracak, ancak geri kalanını olduğu gibi bırakacak ve çıkarma zorunluluğunu ortadan kaldıracaktır.


5
Mükemmel cevap. react-app-rewired[ Github.com/arackaf/customize-cra Başlat ( customize-cra) ile daha fazla yararlanabilirsiniz . Sonra config sadece babelInclude([path.resolve('src'), path.resolve('../common')])ve kullanır removeModuleScopePlugin().
ivosh

Lütfen bu kod pasajını nereye yerleştirmem gerektiğini teyit edebilir misiniz?
bijayshrestha

1
@bijayshrestha Reat-app-rewired projesinin benioku dosyasını okuyun, işte nasıl kurulacağını açıklıyor. Kurulum sırasında config-overrides.js, kodu yerleştirebileceğiniz bir dosya oluşturacaksınız .
Lukas Bach

ModuleScopePluginEklentiyi kaldırmak iyi bir fikir değildir . src
Reat

1
Bu çözüm daktilo ile çalışır mı? TS ile çalışamıyorum.
user3053247

27

Başkalarının cevaplarına biraz daha fazla bilgi sunmak. .Png dosyasını kullanıcıya nasıl teslim edeceğinizle ilgili iki seçeneğiniz vardır. Dosya yapısı seçtiğiniz yönteme uygun olmalıdır. İki seçenek şunlardır:

  1. import x from yReakt-create-app ile sağlanan modül sistemini ( ) kullanın ve JS'nizle paketleyin. Görüntüyü srcklasörün içine yerleştirin .

  2. publicKlasörden sunun ve Düğümün dosyayı sunmasına izin verin. create-tepki-app de görünüşe göre bir ortam değişkeni ile geliyor örn <img src={process.env.PUBLIC_URL + '/img/logo.png'} />;. Bu, React uygulamanızda buna başvurabileceğiniz, ancak yine de tarayıcınız normal bir GET isteğinde ayrı olarak istediği şekilde Düğüm üzerinden sunulmasını sağlayabileceğiniz anlamına gelir.

Kaynak: create-tepki-app


Öneri # 2 tam olarak benim için aşağıdaki hataya neden olan şey: Modül bulunamadı: src / dizini dışında kalan ./../../../public/CheersBar-Drinks-147.jpg dosyasını içe aktarmaya çalıştınız. . Src / dışındaki göreli ithalatlar desteklenmez. Src / içine taşıyabilir veya projenin node_modules / dizininden bir sembolik bağlantı ekleyebilirsiniz.
Amos Long

25

Resimleriniz ortak klasördeyse,

"/images/logo_2016.png"

senin <img> src yerine ithal ait

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

Bu çalışacak

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

2
Benim için çalışmıyor. Aynı mesajı almak - 'src / dizini dışında. Src / dışındaki göreli ithalatlar desteklenmez. '
Arkady

Cevabınız doğru IMO ama <img src="...">içeri aktarma değil , yol hakkında konuştuğunuzu açıklama özgürlüğünü aldım
Dmitry Yudakov

1
Tam da aradığım şey buydu! Basitçe CRA'nın "src" dizinine bir "images" klasörü ekledim ve sonra kullanabildim<img src="/images/logo.png" alt="Logo" />
Amos Long

12

Sen taşımak gerekir WC-BlackonWhite.jpgsenin içine srcdizine. publicDizin (örneğin favicon gibi) HTML doğrudan bağlantılı olduğu da paket içine doğrudan içeri gidiyoruz, değil şeyler oluyor statik dosyalar içindir.


Başkalarının bu şekilde yaptığını gördüm. Bu yüzden bunun doğru yol olduğunu düşündüm
David Brierton

@DavidBrierton: Bu önlem oluşturma-reaksiyon uygulamasının daha yeni bir sürümünde eklenmiş olabilir.
Joe Clay

8

Çözümler sağlayan birkaç cevap var react-app-rewired, ancakcustomize-craremoveModuleScopePlugin() biraz daha zarif olan özel bir API'yi ortaya koyan . (Aynı çözüm, ancak customize-crapaket tarafından soyutlanmış .)

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
günümü kurtardın!
lmiguelvargasf

6

Craco kullanarak çıkarın:

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 için oy verin! Craco, CRA 3.x'i destekliyor
Roman Podlinov

4

Bu kısıtlama tüm dosya veya modüllerin (dışa aktarmaların) src/dizinin içinde , uygulamanın içinde ./node_modules/react-dev-utils/ModuleScopePlugin.jsbulunduğu kod satırlarında olmasını sağlar.

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

Bu kısıtlamayı şu şekilde kaldırabilirsiniz:

  1. bu kod parçasını değiştirme (önerilmez)
  2. veya dahaeject sonra dizinden kaldırın ModuleScopePlugin.js.
  3. veya yorum / kaldır const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');dan./node_modules/react-scripts/config/webpack.config.dev.js

Not: çıkartmanın sonuçlarına dikkat edin .


Teşekkürler @SurajRao, buraya taşındım. Umarım daha iyidir.
its4zahoor

@PattycakeJr Evet, bu yüzden aşağıda çıkarma sonuçlarının eşyası olmayı söyledim.
its4zahoor

3

bu iki paketi yükle

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

Çıkarmanıza gerek yok, react-scriptsyapılandırmayı rescripts kütüphanesi ile değiştirebilirsiniz

Bu, o zaman işe yarar:

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

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

  return config;
};

2

Bence Lukas Bach çözümü kullanımına tepki-app-rewired ise Modifiye webpack yapılandırma amacıyla gitmek için iyi bir yoldur, ancak, ben bütün dışlamak olmaz ModuleScopePlugin ama bunun yerine src dışında alınabilir belirli bir dosya beyaz liste:

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

Bu şimdiye kadarki en iyi çözüm.
adi518

2

Ortak klasörün içindeki resim

  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 içinde resim kullan

1

Yalnızca README.md veya package.json gibi tek bir dosyayı içe aktarmanız gerekiyorsa, bu açıkça ModuleScopePlugin () öğesine eklenebilir

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
Bunun için önce create-tepki-uygulamadan çıkarılması gerekir, değil mi?
Beau Smith


1

Karınca tasarımını kullanırken olduğu gibi birden fazla modifikasyona ihtiyacınız varsa, bunun gibi birden fazla işlevi birleştirebilirsiniz:

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

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

1

Bartek Maciejiczek'in cevabına ek olarak, Craco ile şöyle görünüyor:

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.