16

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?

2 Answers 2

21

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

Sign up to request clarification or add additional context in comments.

7 Comments

+1 yes, I do this too. But how to do you test the resulting react app with Jest? How can I teach Jest to understand the !!raw-loader! directive?
Sorry, I don't have an answer for you there. But be sure to report back if you figure it out!
@counterbeing I believe you are missing an ! in the typing file. !!raw-loader
Doesn't work for me with CRA 5.0.1 it changes the content of the file, but the imported string is still a url from which you have to fetch the file content.
@SashaDavydenko I've abandoned CRA for vite, but if you come up with a solution that works, I'm happy to put a header at the top of the current answer and upvote you :)
|
6

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

1 Comment

what about a solution for VITE?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.