Webpack, courtesy of webpack.js.org
It was Saturday night hanging around to solve the issue of ?ReferenceError: legacyLib is not defined? in my React+Typescript app. I was sure that this error was about my ?legacyLib.js? lib file, which included thousands of lines of code coded as IIFE, which wasn?t bundled by webpack by default.
ReferenceError: legacyLib is not defined./src/index.tsxG:/Projects/GitHub/cra-webpack-config/src/index.tsx:7 4 | import “./index.css”; 5 | import registerServiceWorker from “./registerServiceWorker”; 6 | > 7 | console.log(legacyLib.pageLoadTime); 8 | legacyLib.authorize(); 9 | 10 | ReactDOM.render(<App />, document.getElementById(“root”) as HTMLElement);View compiled
I could solved the issue by manually copying the ?legacyLib.js? file to my app folder or by serving over CDN as follows, but I prefered to do this work by webpack. So let?s start the journey of configuring create-react-app webpack.config.js.
The issue: ?ReferenceError: legacyLib is not defined?
For the sake of simplicity I simplified the ?lib.js? and created ?legacyLib.js? which is a IIFE function with several lines of code. In order to use ?legacyLib.js? with Typescript I defined ?legacyLib.d.ts? typescript definition file.
src/lib/legacyLib.jssrc/lib/legacyLib.d.ts
While coding react app, linter and intellisense was happy with coding. I coded as usual. I was feeling happy that without importing any module in my tsx documents, webpack will understand that I am using ?legacyLib.js? and will include ?legacyLib.js? in Dependency Graph, then bundles accordingly.
My happiness distracted after running npm start:
npm run start
Webpack bundled resources and devserver started without any errors. When browser opened the scary error was there.
ReferenceError: legacyLib is not defined./src/index.tsxG:/Projects/GitHub/cra-webpack-config/src/index.tsx:7…
It was the time that webpack should be configured for react app which was created with create-react-app package. So, I started to configure webpack configurations.
Solution
In order to recreate the issue let?s start by creating the app from scratch. By executing the following command we are creating the project.
create-react-app cra-webpack-config –scripts-version=react-scripts-ts
When command execution completes we will have the following project folder structure:
cra-webpack-config/?? .gitignore?? images.d.ts?? node_modules/?? public/?? src/? ?? …?? package.json?? tsconfig.json?? tsconfig.prod.json?? tsconfig.test.json?? tslint.json
As you can see that we don?t have any webpack.config.js file in our project. That?s because Create-React-App states that we are not allowed to override webpack specific configurations. But we have chance to do so, let?s have a try!
Our motivation was let the webpack to copy ?legacyLib.js? file to build directory. So here plays the CopyWebpackPluginplugin of webpack, which can do exact job what we want.
CopyWebpackPlugin
Webpack has ?CopyWebpackPlugin? plugin which copies desired files or directories to the build directory. It is good news that we have chance to modify webpack configuration to copy our desired file to build folder. So let?s start by installing ?CopyWebpackPlugin? to our app:
npm install -D copy-webpack-plugin
npm install ? save is used when you want a package that should be bundled in production bundle, if you are using a package to enhance your development experience(e.g jest, webpack, etc.) then use npm install ? save-dev or shortly npm i -D.
If our react app project was created manually, we could easily modified webpack configuration by adding webpack.config.js file in root folder of project layout. The following lines would be added to webpack.config.json file when webpack was installed manually:
react-app-rewired
Since we have created our project with create-react-app package we can?t simply modify webpack.config.json file. In order to achieve our goal we will use react-app-rewired package. So let?s install react-app-rewired:
npm i -D react-app-rewired
The react-app-rewired package is used to configure webpack configurations, so it is development dependency that?s why we installed as ? save-dev.
After installing react-app-rewired package, manually create config-overrides.js file in the root directory.
cra-webpack-config/?? .gitignore?? images.d.ts?? node_modules/?? public/?? src/? ?? …?? package.json?? tsconfig.json?? tsconfig.prod.json?? tsconfig.test.json?? tslint.json?? config-overrides.js
And the last modification in package.json file in ?scripts? section.
// package.json”scripts”: { – “start”:”react-scripts-ts start”, + “start”: “react-app-rewired start –scripts-version react-scripts-ts”, – “build” “react-scripts-ts build”, + “build”: “react-app-rewired build –scripts-version react-scripts-ts”, – “test”: “react-scripts-ts test –env=jsdom”, + “test”: “react-app-rewired test –env=jsdom –scripts-version react-scripts-ts”, “eject”: “react-scripts-ts eject” }
Don?t forget to add <script> tag in public/index.html file. Let’s add the tag.
After modifications are finished, let?s start the dev server.
npm start
And that?s it! Webpack has copied our ?legacyLib.js? in our build directory. You can access source code of this project from GitHub.