Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to import a file into a react app that uses create react app as raw text?

Goals

  1. I want to display some code for reference from the project itself.
  2. I want the display of the code to be updated with the implementation.
  3. I don't want to eject from create-react-app

This react project, created with create-react-app and typescript, is going to be used to display some custom components for re-use in other projects. My goal is to have the component be used right next to the code that is using it.

How can I load the file if I don't have access to the webpack config, and I can't use fs.readFile?

like image 593
counterbeing Avatar asked Apr 09 '20 19:04

counterbeing


2 Answers

I managed to get this working after a bit of looking around. There are two major pieces that had to be in place to make it work.

Use the appropriate loader

In this case I wanted to use the raw-loader, so I installed it as a dev dependency. yarn add -D raw-loader.

In order to actually import the file I needed to then override the webpack configuration like this:

// eslint-disable-next-line import/no-webpack-loader-syntax
import toolbarItems from '!!raw-loader!../ToolbarItems';

This loads the entire file into the variable toolbarItems. By using the !! before the loader I prevent any other webpack loaders from processing it in this specific case. This might work on its own in a plain javascript project, but in typescript...

You must provide a module to typescript

I was running into the typescript error:

Failed to compile.

/Users/cory/Code/something/custom-theme/src/pages/NavigationDemo.tsx
TypeScript error in /Users/cory/Code/something/custom-theme/src/pages/NavigationDemo.tsx(9,26):
Cannot find module '!!raw-loader!../ToolbarItems'.  TS2307

     7 |
     8 | // eslint-disable-next-line import/no-webpack-loader-syntax
  >  9 | import toolbarItems from '!!raw-loader!../ToolbarItems';
       |                          ^
    10 |
    11 | const useStyles = makeStyles({
    12 |   root: {

Simply declaring a module for the loader in a file called ToolbarItems.ts.d.ts solved the issue for me:

declare module '!!raw-loader!*' {
  const content: string;
  export default content;
}

source

like image 87
counterbeing Avatar answered Oct 14 '22 04:10

counterbeing


Since you use create-react-app for your project, the best solution at the moment would be a babel plugin called Raw.Macro.

This plugin allows you to access content of your files without a need to create-react-app eject. Provides really elegant solution without any boilerplate code and declaring "d.ts" files as in previous answer.

Note: There is a small drawback that you have to re-start your webpack dev server when the file changes, because the content of a file is being embedded during the build process.

import raw from 'raw.macro';

function foo(){
    const jsonContent = raw('../utils/stops.json');
    console.log(jsonContent);
}
like image 28
Marcel Šerý Avatar answered Oct 14 '22 05:10

Marcel Šerý