I would like to place a TS file outside of the project scope, in a different folder, and importing it from there in 2 or more SPFx projects.
example folder structure:
Root
Want to use Utilities.ts in both SPFx projects.
I don't mind it being bundled in the web part, but wouldn't want to have to go to the trouble of setting it up as an npm package.
When I do it, VSCode works fine, finds the TS file and shows the correct auto-complete for types, but gulp serve breaks and says module cannot be found.
Problems are:
Create a root folder
Create 2 separate SPFx project under it
Create "SharedCode" folder under the root
Create a Utilities.ts file under SharedCode, with code similar to this:
import { IWebPartContext } from "../SPFxProj1/node_modules/@microsoft/sp-webpart-base";
export default class Utilities {
public static GetUserName(ctx: IWebPartContext): string {
return ctx && ctx.pageContext && ctx.pageContext.user && ctx.pageContext.user.displayName || 'Anonymous user';
}
}
Use it inside SPFxProj1 and SPFxProj2
You will see SPFxProj2 complains about type mismatch.
Try to run gulp serve on SPFxProj1, you will see gulp serve issues a webpack error.
IMHO, I'd rather not see the SPFx team do anything in this area as this isn't a SPFx thing... again IMHO. It's no different than creating a class library (*.dll) in a .NET project.
This is a common scenario in JavaScript libraries distributed with NPM... why not just include it in your own NPM module and publish that to the NPM JS registry? If it contains code you don't want others to have access to, make it a private module. The other option (which I prefer) is to install it straight from a private repo...
This approach is ideal IMHO because it's true code reuse and it's refactored away from both other projects, plus it is independently versioned.
For instance, here's a snippet from a package.json from a private project I'm working on that uses a private repo:
"dependencies": {
"amqplib": "0.4.2",
"moment": "2.14.1",
"request": "2.74.0",
"voyager-shared": "github:andrewconnell/voyager-shared"
},
The voyager-shared repo is in a private repo in my GitHub account. Authentication to GitHub is handled using SSH.
In case anyone is interested, I just figured what I was missing.
It turns out to be a type script compiling issue. I just needed a tsconfig.json in my SharedCode folder, and to compile it (using tsc command) to produce the JS file for it.
While I understand where you are coming from @andrewconnell, I do see value in this. See, not every utility function needs to become a package in my opinion, and if my source control is not in GitHub I don't see why I would need to place that specific shared code in GitHub. I assume not everyone out there are using GitHub as their source control, and would like all their code stored at one central location.
In any case, there is nothing for the team here to consider, since it is doable. I just still didn't figure out how to make that build as a part of the gulp task, but I am sure it is an easy change to the gulpfile.js
@andrewconnell have to admit you made me take a third look at it, and I figured with npm init to create the package in a relative folder, I can then define the dependency to a relative folder, while keeping all of them within the same source control the way I want it.
Now, this makes a lot more sense. I will start changing my code to do it this way.
Thanks for that, again nothing for the product team to see here.
(Only thing I don't like is having to "npm update" each project when I have a new version)
Issues that have been closed & had no follow-up activity for at least 7 days are automatically locked. Please refer to our wiki for more details, including how to remediate this action if you feel this was done prematurely or in error: Issue List: Our approach to locked issues
Most helpful comment
@andrewconnell have to admit you made me take a third look at it, and I figured with npm init to create the package in a relative folder, I can then define the dependency to a relative folder, while keeping all of them within the same source control the way I want it.
Now, this makes a lot more sense. I will start changing my code to do it this way.
Thanks for that, again nothing for the product team to see here.
(Only thing I don't like is having to "npm update" each project when I have a new version)