s-KaiNet / spfx-fast-serve

Improve your SharePoint Framework development flow by speeding up the "serve" command :rocket:
MIT License
138 stars 11 forks source link

Doesn't work with PNPM #143

Closed AhmadiRamin closed 3 months ago

AhmadiRamin commented 4 months ago

Hi

I have a solution with a library project and normal spfx project, I'm also using pnpm instead of npm.

when I make any changes to the library project it doesn't do anything unless I stop it and run it again!

any idea?

s-KaiNet commented 4 months ago

Do you use the latest 1.19.2 version of spfx-fast-serve-helpers?

AhmadiRamin commented 4 months ago

Hi Sergei, thank you for your response.

I'm using version 1.18.0: "spfx-fast-serve-helpers": "~1.18.0",

I'm also using SPFx version 1.18.2.

I created two simple SPFx projects (one library, one web part) and followed the steps to set up SPFx Fast Serve, but I encountered the same issue again. I'm not sure if the problem is related to pnpm or the Fast Serve library.

s-KaiNet commented 4 months ago

Have you followed this configuration guide?

AhmadiRamin commented 4 months ago

Yes I have

s-KaiNet commented 4 months ago

Strange enough, I will check later in the evening what might be wrong there.

AhmadiRamin commented 4 months ago

Thanks Sergei, I can upload the files somewhere in GitHub for you if needed?

s-KaiNet commented 4 months ago

No, it's quite simple setup I guess. I will follow my own guide for library components, but use pnpm instead, and I will be able reproduce the issue, right?

AhmadiRamin commented 4 months ago

yeah that's right

s-KaiNet commented 4 months ago

Could you share your setup, where the issue was reproduced? I've tried and for me everything works just fine. I use pnpm 9.x

AhmadiRamin commented 4 months ago

I'm using pnpm 7.24.3 node 16.18.1 spfx 1.18.2

s-KaiNet commented 4 months ago

try upgrading pnpm, previously it was an issue with wrong dep resolution for earlier pnpm versions.

AhmadiRamin commented 4 months ago

How did you link your SPFx project with the library project? Did you use pnpm link 'library path'? Additionally, for the library project, did you run gulp build or gulp bundle --ship before running npx fast-serve? I'm trying to figure out what I might have missed.

s-KaiNet commented 4 months ago

How did you link your SPFx project with the library project? Did you use pnpm link 'library path'? Additionally, for the library project, did you run gulp build or gulp bundle --ship before running npx fast-serve? I'm trying to figure out what I might have missed.

I just followed the steps from the guide, nothing more.

s-KaiNet commented 4 months ago

to link i run pnpm install ../<spfx library folder name> --save

AhmadiRamin commented 4 months ago

I'm going to upgrade my versions of pnpm and Node to see if that resolves the issue.

AhmadiRamin commented 4 months ago

I've upgraded my packages to:

pnpm: 9.6.0 node: 18.18.2

Then I cleaned both projects, removed the node_modules folder, and re-ran pnpm i. The pnpm run serve command works fine in the library project without any errors, but I encountered the following error in the web parts project. Do I need to install and configure webpack loaders? It's just a simple hello world web part without any customization.

Error - [webpack] 'dist': ./lib/webparts/helloWorld/assets/welcome-light.png Module build failed (from ./node_modules/.pnpm/file-loader@6.1.0_webpack@4.47.0webpack-cli@4.10.0/node_modules/file-loader/dist/cjs.js): Error: error:0308010C:digital envelope routines::unsupported

Error: error:0308010C:digital envelope routines::unsupported at new Hash (node:internal/crypto/hash:69:19) at Object.createHash (node:crypto:133:10) at getHashDigest (C:/Dev/SPFx/pnpm-workspace/spfx-webparts/node_modules/.pnpm/loader-utils@2.0.0/node_modules/loader-utils/lib/getHashDigest.js:46:34)

s-KaiNet commented 4 months ago

no you don't need to configure anything. most likely you haven't deleted pnpm-lock.yaml. You sould delete both pnpm-lock.yaml and node-modules, then reinstall.

AhmadiRamin commented 4 months ago

it didn't work, I removed everything and created a fresh library project and spfx project but got the same error, here is the package.json:

{ "name": "spfx-webparts", "version": "0.0.1", "private": true, "engines": { "node": ">=16.13.0 <17.0.0 || >=18.17.1 <19.0.0" }, "main": "lib/index.js", "scripts": { "build": "gulp bundle", "clean": "gulp clean", "test": "gulp test", "serve": "fast-serve" }, "dependencies": { "@fluentui/react": "^8.106.4", "@microsoft/sp-component-base": "1.18.2", "@microsoft/sp-core-library": "1.18.2", "@microsoft/sp-lodash-subset": "1.18.2", "@microsoft/sp-office-ui-fabric-core": "1.18.2", "@microsoft/sp-property-pane": "1.18.2", "@microsoft/sp-webpart-base": "1.18.2", "react": "17.0.1", "react-dom": "17.0.1", "spfx-library": "link:..\\spfx-library", "tslib": "2.3.1" }, "devDependencies": { "@microsoft/eslint-config-spfx": "1.18.2", "@microsoft/eslint-plugin-spfx": "1.18.2", "@microsoft/rush-stack-compiler-4.7": "0.1.0", "@microsoft/sp-build-web": "1.18.2", "@microsoft/sp-module-interfaces": "1.18.2", "@rushstack/eslint-config": "2.5.1", "@types/react": "17.0.45", "@types/react-dom": "17.0.17", "@types/webpack-env": "~1.15.2", "ajv": "^6.12.5", "eslint": "8.7.0", "eslint-plugin-react-hooks": "4.3.0", "gulp": "4.0.2", "spfx-fast-serve-helpers": "~1.18.13", "typescript": "4.7.4" } }

Can you please share your code with me?

Here is the error I get:

Error - [webpack] 'dist': ./lib/webparts/helloWorld/assets/welcome-dark.png Module build failed (from ./node_modules/.pnpm/file-loader@6.1.0_webpack@4.47.0webpack-cli@4.10.0/node_modules/file-loader/dist/cjs.js): Error: error:0308010C:digital envelope routines::unsupported at new Hash (node:internal/crypto/hash:69:19) at Object.createHash (node:crypto:133:10) at getHashDigest (C:/Dev/SPFx/fast-serve/spfx-webparts/node_modules/.pnpm/loader-utils@2.0.0/node_modules/loader-utils/lib/getHashDigest.js:46:34)

s-KaiNet commented 4 months ago

I was able to reproduce it with pnpm@9.6, but strange enough I used pnpm@9.0.5 and it worked fine. But the problem is, that it's regular gulp bundle throws the error, not fast-serve, spfx cannot bundle the project with pnpm@9.6 for some reason. My recommendation would be using pnpm@9.0.5 or may be pnpm@8.15.7 should also work.

AhmadiRamin commented 4 months ago

yeah it's very strange, I fixed that issue, I noticed there are two file-loader under node_modules .pnpm folder: -file-loader@6.1.0_webpack@4.47.0webpack-cli@4.10.0 -file-loader@6.2.0_webpack@4.47.0webpack-cli@4.10.0

I removed the node_modules and the lock file, installed a version of file-loader compatible with webpack 4.x: pnpm add file-loader@4.3.0 -D

also added a following resolution section in package.json to prevent conflicts:

"resolutions": { "file-loader": "4.3.0" }

and it started working!

s-KaiNet commented 4 months ago

It's ok that there are two versions, acutally fast-serve requires file-loader 6.x. The actual problem is in node and this issue. So my recommendation still will be using pnpm@9.0.5 or pnpm@8.15.7 and don't change package.json.

AhmadiRamin commented 4 months ago

I downgraded pnpm to 9.0.5 and removed the changed I made earlier and I got that error again, what is your node version?

s-KaiNet commented 4 months ago

I use 18.17.1

s-KaiNet commented 4 months ago

Ok it's a total mess. So I have: pnpm 9.6, node 18.17

I created the initial project with pnpm - hello world webpart, added fast-serve. run it - everything works fine. Then I deleted node_modules, pnpm-lock.yaml, run pnpm i, then gulp bundle - I see your error. I have to dig deeper to understand why it happens. It looks like on fresh install the dep tree is different, I don't know why.

AhmadiRamin commented 4 months ago

yeah it's very strange, I installed node 18.17.1 and still getting that error.

s-KaiNet commented 4 months ago

Ok seems I managed to fix it. On a project, where you see this error, isntall the latest fast-serve: pnpm i spfx-fast-serve-helpers@1.18.14 -DE. This should fix the issue.

AhmadiRamin commented 4 months ago

Amazing! That solves the errors. After testing it with a simple library and web part projects, I thought I was ready to enable it in our large project, which includes a library and many web part projects. However, I'm facing the first issue again: when I make changes to the library, it starts compiling, but once it's done, I can't see the changes until I stop and restart it.

s-KaiNet commented 4 months ago

As I understand, it works for you for simple setup, but doesn't work for your project.
In this case could you tell me more about your project setup? Have you checked, that in a library component folder, under fast-serve/config.json you have right configuration (should be isLibraryComponent: true under serve node)? How many library components you have? How many SPFx solutions (by solution I mean a separate folder where all the SPFx components reside - web parts, app customizers, etc.)? What library component exports - just various helper classes, react components or anything else? Do you use any pnpm specific features, like workspaces maybe? If yes, how have your configured workspaces? How do you import classes from library components? Could you provide small code sample?

AhmadiRamin commented 4 months ago

I've checked everything. Our library project includes components, services, utilities, etc. We are not using pnpm workspaces.

I noticed something strange. For our library project, we use a name like @libraries/shared. I suspected the issue might be related to the name, so I updated the library name to @libraries/shared in a sample project that was working. I also updated the package.json in the web part project to:

"@libraries/shared": "link:..\\spfx-library"

After cleaning and resetting everything, it stopped working. Changes to the library no longer updated or refreshed the page. However, as soon as I reverted the changes, it started working again.

I've uploaded that sample project here if you want to give it a try.

Thank you so much for helping me, really appreciated.

s-KaiNet commented 4 months ago

Wow, that's interesting! Thank you for the sample, will take a look.

s-KaiNet commented 4 months ago

Well, actually the problem is here. Normally, you should use just

import { SharedLibrary } from '@libraries/shared';

Your library component is just a npm dependency, thus you should import like from a normal npm module.

AhmadiRamin commented 4 months ago

That's interesting. It might be because this project was set up a few years ago. I noticed that the imports are always like @libraries/shared/lib/components/.... When I looked deeper, I saw that even imports from Fluent UI follow the same format:

import { ITooltipHostStyles, TooltipHost, TooltipOverflowMode } from '@fluentui/react/lib/Tooltip';

and it doesn't work if I remove the lib from the path.

s-KaiNet commented 4 months ago

It makes sense for third party libraries like fluent ui, but for library component to work with fast-serve you should always import from root. From technical perspective the result is absolutely the same, but imports from root it's the only way to fast-serve to correctly work with library components.

AhmadiRamin commented 4 months ago

Thanks, Sergei, for your help. I can confirm that imports from the root are working. Now, I need to evaluate if it's worthwhile to update all of our projects to use this approach.

AhmadiRamin commented 4 months ago

Is it possible to clone the spfx-fast-serve-libraries and customize it to support non-root imports?

s-KaiNet commented 4 months ago

Is it possible to clone the spfx-fast-serve-libraries and customize it to support non-root imports?

First of all these are the same:

import { SharedLibrary } from '@libraries/shared/lib/index';
import { SharedLibrary } from '@libraries/shared';

So it should be just a replacement in all the source files.

But if you still want to use non-root, you can try an alternative approach:

  1. Install concurrently - pnpm i concurrently -DE
  2. Update your spfx lib project's package.json and add below npm run scripts:
    "ts-watch": "npx tsc -p tsconfig.json --watch",
    "serve-ts": "concurrently \"npm run ts-watch\" \"npm run serve\""
  1. In lib component project run npm run serve-ts. Wait when bundle is finished. Then run normal npm run serve in the webparts project.

Now when you change a file inside library project, TS compiler (tsc) will output it into the lib, so you will be able to see the changes. I haven't tested this approach widly, but you can try maybe it will be ok for your project.

s-KaiNet commented 4 months ago

Edit a bit nicer and we don't need npx inside npm scripts:

    "ts-watch": "tsc -p tsconfig.json --watch --preserveWatchOutput",
    "serve-ts": "concurrently \"npm run ts-watch\" \"npm run serve\""
AhmadiRamin commented 4 months ago

Thanks, Sergei. I'm going to give it a try. The reason I can't go with root imports is that our solution is very large, containing many projects, and updating them all would take too much time.

AhmadiRamin commented 3 months ago

Hi Sergei, I've tested your solution and it works, but only for .ts, and .tsx files, do you know how can I get updates for the .scss files?