Reputation: 728
I have a .NET Core 3.1 ASP.Net project using razor views.
I'm using React components in those razor views by adding app.UseReact() to my startup.cs and then calling @html.React("myComponent") inside the .cshtml files. I'm not using React as an SPA.
This works fine when I have "myComponent" inside a .tsx file that's in the web project.
My company want to move some of these react components into npm packages so that they can be re-usable across projects. After moving the .tsx file for "myComponent" to an npm package, and referencing the package in package.json, upon running the project I get the error "myComponent" is not defined.
I've run a npm install and I can see that the package and the .tsx file for "myComponent" are in the node_modules folder of the project, but I'm guessing that asp.net mvc doesn't know to look in there for components when I'm calling @html.React("myComponent") inside the .cshtml file.
What do I need to do to make asp.net find the component? Do I need to explicitly import it somehow?
For now, I've managed to get by with a dirty hack. I'm using a pre-build script to copy the component's tsx file out of the node_modules folder and into the ClientApp folder, so that it sits along with the projects other react components. But it's not ideal because another developer may not realise that it's being copied there and try to edit it if they want to make changes, when really they should be editing the file in the npm package.
Upvotes: 1
Views: 6434
Reputation: 1370
Direct Answer
Adding an npm package does not make it available to MVC automatically so you'll have to do some sort of file copy at some point in your development cycle. This can be a npm postinstall
script or even something more complex such as a Grunt/Gulp task. You can even trigger the tasks via npm scripts if you choose to do so. All and all there's no "right" or "standard" way of doing react with MVC so you're free to make your own choices, carefully :)
if they want to make changes, when really they should be editing the file in the npm package.
Yes they will need to know about the npm package, clone its source git, update it, publish it, then update their project to the latest package version.
My Experience (read pain)
How can I forget this pain. It was a mistake to have React as a non-SPA because you're essentially making every main view an independent SPA and this has some major drawbacks. Firstly how do you share data between razor view and the component on the same page? The way we did it was to JSON stringify the data into a variable and then load this variable in the component (you can also opt-in for an additional http call to a web api endpoint). You can already see the start of fire as the pages evolve over time. Next problem we came across was bundling optimizations. We had to write a bunch of code in order to bundle per page and save outputs to the wwwroot
folder. Developers coming on board often confused as to what this does in main razor views (e.g. Views/Home/Index.cshtml):
<script src="/Home.Index.min.js"></script>
Wait where is the /Home.Index.min.js
file? This is created by the bundling task for this page at build time and copied to the scripts folder. Next question a developer would ask was why the page is missing its "user interface", of course they've forgotten to add an additional task for the new razor page they created (well and the script entry)... I can write for days on how terrible the idea of one bundle per razor page was and how messy the code became a few years into the maintenance cycle, not to mention the mysterious comeback of JQuery!!. The truth is that JS needs to be tree-shaken, minified and optimized. ASP.NET has no such a thing, the nuget packages simply glue your JS files and provide some level of minification, none of which can match standard bundlers such as webpack or parcel. This was another reason to have our bundling tasks run a bundler for each page. This also took care of the npm dependencies and third-party libraries.
My Recommendation (opinionated)
Save yourself and simply keep them separate. There's no such a thing as a razor page with react, that's a made up hack to make razor compatible with the evolved web technologies. Some of this applies to php so it's not just a Microsoft thing.
Best you can do is to create a SPA and use web api for back-end. You can have razor but they will be independent pages, for example the login page can be a razor page which then takes you to the home page that's a SPA written and bundled via react and the surrounding ecosystem. Interactions in the SPA happen over REST or even GraphQL apis.
Upvotes: 6