DEV Community

Jastria Rahmat
Jastria Rahmat

Posted on • Edited on

Adding react-pdf to Create React App with Craco

Introduction

As of the current date (2023-06-15), adding react-pdf to a Create React App (CRA) project by default is not possible due to the upgraded Webpack version in CRA to Webpack 5. However, we can use Craco, a tool that allows us to modify the Webpack configuration without ejecting from CRA, to safely integrate react-pdf into our project.

To understand why we need to use Craco and how it helps us overcome the limitations, you can refer to this comment on GitHub: react-pdf issue #1029.

Steps

Step 1: Initialize the project

Initialize the project by running the following command in your terminal:

npm init react-app react-pdf-cra
Enter fullscreen mode Exit fullscreen mode

or

yarn create react-app react-pdf-cra
Enter fullscreen mode Exit fullscreen mode

Then navigate to the project directory:

cd react-pdf-cra
Enter fullscreen mode Exit fullscreen mode

Step 2: Add the required dependencies

Install the required dependencies by running the following command:

npm install @react-pdf/renderer browserify-fs node-polyfill-webpack-plugin process webpack pako assert browserify-zlib buffer process stream-browserify util
Enter fullscreen mode Exit fullscreen mode

or

yarn add @react-pdf/renderer browserify-fs node-polyfill-webpack-plugin process webpack pako assert browserify-zlib buffer process stream-browserify util
Enter fullscreen mode Exit fullscreen mode

The dependencies include:

  • @react-pdf/renderer: The main library for creating PDFs using React components.
  • browserify-fs: A browserify-compatible version of the Node.js fs module.
  • node-polyfill-webpack-plugin: A Webpack plugin that provides polyfills for Node.js core modules.
  • process: A browser-compatible version of the Node.js process object.
  • webpack: The Webpack module bundler.
  • pako: A zlib implementation in JavaScript.
  • assert: The Node.js assert module.
  • browserify-zlib: A browserify-compatible version of the Node.js zlib module.
  • buffer: A browserify-compatible version of the Node.js buffer module.
  • stream-browserify: A browserify-compatible version of the Node.js stream module.
  • util: The Node.js util module.

For the development dependency, install:

npm install -D @craco/craco
Enter fullscreen mode Exit fullscreen mode

or

yarn add -D @craco/craco
Enter fullscreen mode Exit fullscreen mode

Step 3: Initialize Craco

Replace the package.json scripts with:

"scripts": {
  "start": "craco start",
  "build": "craco build",
  "test": "craco test",
  "eject": "craco eject"
}
Enter fullscreen mode Exit fullscreen mode

Create a craco.config.js file in the project's root directory:

touch craco.config.js
Enter fullscreen mode Exit fullscreen mode

Inside the craco.config.js file, add the following configuration:

const webpack = require("webpack");
const NodePolyfillPlugin = require("node-polyfill-webpack-plugin");

module.exports = {
  webpack: {
    configure: {
      resolve: {
        fallback: {
          process: require.resolve("process/browser"),
          zlib: require.resolve('@react-pdf/zlib'),
          stream: require.resolve("stream-browserify"),
          util: require.resolve("util"),
          buffer: require.resolve("buffer"),
          asset: require.resolve("assert"),
          fs: require.resolve('browserify-fs'),
        },
      },
      plugins: [
        new webpack.ProvidePlugin({
          Buffer: ["buffer",

 "Buffer"],
          process: "process/browser.js",
        }),
        new NodePolyfillPlugin(),
      ],
    },
  },
};
Enter fullscreen mode Exit fullscreen mode

Step 4: Modify the App component

Replace the contents of ./src/App.js with the following code:

import "./App.css";
import React from "react";
import { Page, Text, View, Document, StyleSheet } from "@react-pdf/renderer";

// Create styles
const styles = StyleSheet.create({
  page: {
    flexDirection: "row",
    backgroundColor: "#E4E4E4",
  },
  section: {
    margin: 10,
    padding: 10,
    flexGrow: 1,
  },
});

function App() {
  return (
    <div className="App">
      <Document>
        <Page size="A4" style={styles.page}>
          <View style={styles.section}>
            <Text>Section #1</Text>
          </View>
          <View style={styles.section}>
            <Text>Section #2</Text>
          </View>
        </Page>
      </Document>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Step 5: Run the application

Start the application by running the following command:

npm start
Enter fullscreen mode Exit fullscreen mode

or

yarn start
Enter fullscreen mode Exit fullscreen mode

The application should now be running, and you should see the PDF displayed.

Conclusion

In conclusion, by using Craco and modifying the Webpack configuration, we can integrate react-pdf into a Create React App project without the need to eject. This allows us to leverage the power of React components to create PDFs within our application.

Certainly! Here's the updated version with the Troubleshooting section added:

Troubleshooting

If you encounter an error message like Module not found: Error: ...... You attempted to import which falls outside of the project src/ directory. Relative imports outside of src/ are not supported., you can try the following steps to resolve it:

  1. Open the craco.config.js file.

  2. Replace the existing content with the following code:

    const webpack = require("webpack");
    const NodePolyfillPlugin = require("node-polyfill-webpack-plugin");
    
    const baseConfig = {
      webpack: {
        configure: {
          resolve: {
            fallback: {
              process: require.resolve("process/browser"),
              zlib: require.resolve('@react-pdf/zlib'),
              stream: require.resolve("stream-browserify"),
              util: require.resolve("util"),
              buffer: require.resolve("buffer"),
              asset: require.resolve("assert"),
              fs: require.resolve('browserify-fs'),
            },
          },
          plugins: [
            new webpack.ProvidePlugin({
              Buffer: ["buffer", "Buffer"],
              process: "process/browser.js",
            }),
            new NodePolyfillPlugin(),
          ],
        },
      },
    };
    
    const additionalConfig = {
      webpack: {
        configure: webpackConfig => {
          const scopePluginIndex = webpackConfig.resolve.plugins.findIndex(
            ({ constructor }) => constructor && constructor.name === 'ModuleScopePlugin'
          );
          webpackConfig.resolve.plugins.splice(scopePluginIndex, 1);
          return webpackConfig;
        },
      },
    };
    
    module.exports = {
      ...baseConfig,
      ...additionalConfig,
    };
    
  3. Save the changes to the craco.config.js file.

By applying these modifications to the configuration, the error related to module imports outside of the src/ directory should be resolved.

Sources

Top comments (0)