As I'm sure your aware AngularJS is going the way of the Dinosaurs next June being fully taken off of life support. As that is the case many companies are forced to move to new technologies such as React, modern Angular, Vue, or even Svelte.
I recently joined a company that was going through such a transition. The purpose of this article is to explain the process we took moving from AngularJS to React.
The Setup
We decided to take the React transition in a couple of steps. Since AngularJS is a framework and React is a library they can coexist in the same project. However that should not be the end goal. The end goal should be to have a fully functioning React app with no trace of AngularJS left. This is easier said than done.
The are 2 ways you can go about this.
- Start from scratch.
This is probably the easiest way to move from AngularJS to React. You create a new React project by CRA (create React app). Then you can either keep it in tact or eject if you want to customize the webpack options. Then you go about building your application in React. And you probably won't even need to read the rest of this article.
- Integrate React into your current AngularJS project
This is the hardest method. There are many moving parts and this will take the longest depending on the state of your AngularJS application and how modular it currently is. You'll need to add some things before hand if you want to go down this road. But be warned, this path is not for the faint of heart as it will challenge not only your resolve but also your product timelines as unforeseen issues will come up. You'll probably ask yourself at some point during the process what you did to deserve such a fate, but don't worry it will all pay off.
We decided to go with option 2. Why? you may ask. Well, our application is pretty large and has millions of internal and external customers many of whom are still using IE11 plus we have applications in Flex flash (yea, that still is being used) that also needed to be converted over as well before its EOL In December.
In order to make this move we needed to make a list of what we needed.
Webpack
A package to bridge the gap between AngularJS and React
A method of converting AngularJS to React
Obviously, there are many moving parts here and this article can only cover so much. So this will be a series that will cover the steps we took to slowly convert to React.
Welcome to article 1.
Introducing Webpack
This is probably the most important step, without setting up webpack moving to React is much harder. This is because webpack helps to move the application from total DI (Dependency Injection) to imports which will allow you to bundle your application, use code splitting, HMR (Hot Module Replacement), and live reload during development.
This article will assume you already know some things about webpack. If your starting from no knowledge of webpack, I'd recommend reading the documentation and even taking a course on it. Knowledge of webpack will help you long after the project is done.
Installation
However, before you install webpack you'll first need to examine your application and think through a couple of things especially if the AngularJS application you're working with is pretty old. Some questions to ponder could be: What will be the entry point? What loaders will you need? How much of your application is dependent on DI? How should you handle vendor files if you have them? What about templates? Are there nested templates using ng-include? I could go on and on, you get the point. Think through the implementation now and you'll save yourself a lot of trouble later on.
I decided to go with the css, babel, less, html, url and file loaders. For plugins we went with the webpack progress and the HTML webpack plugin. There are more plugins and loaders you can use for your specific needs. I encourage you to research them.
I also set up Dev, QA and Prod webpack files. Then installed webpack-merge to combine the correct env file when needed. This allows you to have different env options contained in different files without polluting your main webpack.config file making it more readable.
When webpack merge runs it examines your webpack config file then based on the env copies the env specific options you set up and merges them with the config file and executes it. I like this set up much more than previous ones.
You can also use presets which allow you to create new options and run them without affecting your config file or env files.
Finally, I added scripts to the package.json file to ensure an easy way to executing the envs for webpack builds.
If you'd like to know more about this leave a comment letting me know and I'll write an article on it in the future.
Application Setup
Once you have your webpack configurations set up you'll need to set up your entry point. I imported all of the vendor files into my entry point. Once that was done I went through and added an index.js file to each component folder and imported everything from that folder there.
I repeated this process for all of the components. This is necessary because even though AngularJS knows what should be included via DI, webpack has no idea what is needed in the bundle unless it's explicitly stated through an import statement, so we have to use this method to ensure all of our files are included into the bundle.
AngularJS Templates
Next on the list was how to ensure all of the AngularJS templates were included in the bundle. The best way I found to include them in the bundle was to change the templateUrl to template and the path to a require with the path. This would ensure the templates would be in the bundle.
Here is a before and after.
Before:
templateUrl: 'nameOfYourTemplate.html'
After:
template: require('./path/nameOfYourTemplate.html')
AngularJS can usually find your templates as long as they are uniquely named but this won't work for webpackAfter:
In order to include them in the webpack bundle we need to require the absolute path to the templates
The other tricky thing was the templates that weren't directly included in the component but nested in another template by using ng-include. Webpack has no idea what ng-include is or does so it just ignores it. You could get a package to handle this as well.
However, the best way I found around this was creating a directive (or component) for the template then using the directive syntax in the other template to include the nested one. The reason I chose this way is because once you start to rewrite all your angularJS code you will automatically know which templates are nested inside others which will make it easier on your later. It sounds more complicated than it is, below is an example.
ng-include directive:
<div ng-include= " 'templateId.html' "></div>
The ng-include is itself a directive however, webpack can't understand that the template should be included
This is the directive I created:
angular
.module('WhatEverYouWant', [])
.directive('newDirective', function() {
return {template: require('./path/nameOfYourTemplate.html')}
})
After you create this you just need to add it to your main DI list by the name you called your module in quotationsThis is the new directive included in the template below. You'll notice that the directive it self has hyphens when placed in a template but does not have hyphens when you created it.
This is because if you were to put hyphens in your directive when you created it, AngularJS would strip them out anyway. So it's best practice to camel case when you're creating the directive and hyphenate when using it.
To use your new directive in another template just add it with hyphens inside of a div tag where ever you want shown here:
<div>
<h1>My new directive</h1>
<div new-directive ></div>
</div>
Floating Variables and CSS
Next, I had to tackle what I like to call "floating variables". You may ask, "what do you mean by floating variables?" Well, in AngularJS land you can create variables and just use them anywhere in your application (unless you're using them in a template) without importing them. This is because AngularJS makes these variables global.
Now, that might fly for AngularJS but webpack and React is going to call you on that real quick. So I had run through the main file where functions and variables were declared for the entire application and export them. Then I imported them into the files that depended them so they would be included in the bundle. This by far took the longest to do, since this was an enterprise application there are a ton of variables and functions used in all parts of the application.
Finally, you'll want to import your css or preprocessed style file(s) into your entry to be included in the bundle and processed by one more more of your loaders. I would recommend to make this easier, import all of your css files into one file and import that one file into your entry. This will ensure all your styles are included in the bundle.
After completing these steps I finally moved to running webpack. (Yea, I haven't even started up webpack at this point.)
Starting The Webpack Build
By now I'm sure you starting to see this process is not an easy one. We've done a lot of work and we haven't even ran webpack yet. This was intentional, the thought process and setup really should be the hardest part of this because if you do the work in the beginning you have to do less work later on and less bugs to squash when you add React.
If you have a backend that is on another server and you want to use webpack-dev-server, you will probably need to setup a proxy for it. Here is the documentation for that, it's not too hard to set up.
After you start the webpack build process your expectation should be that your application builds without errors. If you do see build errors, they may happen because some dependency was missed or a file wasn't imported correctly.
Once the build errors are resolved and it builds successfully, your expectation should be that your application loads in the browser. You will most likely see some errors pop up. That's okay and it is expected.
Test your application meticulously to ensure all of those errors are resolved. This includes undefined variables, styles not being applied, scoping issues, templates that you should see but don't, etc. This will take you a while depending on the size and flow of your application.
Part One Conclusion
Webpack is the first and most important part of the migration from AngularJS to React. Hopefully, part one of the series helped you get your migration off to a great start. I'm currently working on writing part two and should have that out at some point in the future.
If you enjoyed this article, feel free to follow me and check out my other articles I've written here.
Top comments (0)