You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
If I add a symlink in my src directory to another directory, and then include files from that path, create-react-app gives an error:
Module parse failed: Unexpected token
You may need an appropriate loader to handle this file type.
I assume create-react-app wants to have this import already built/transpiled. I would expect this to be the case for imports outside the src directory (node_modules for example). But since the symlink resides in the src directory, I would assume create-react-app would fetch these files as if they were truly in src directory.
Is this a bug, or expected behaviour? It makes it really hard to extract common components.
It sounds like a bug, but this should be working. Can you give more details to reproduce this easily & some test files? A repo with README would be fantastic.
I am trying to share components between projects, so I would like to have these components in another directory and symlink to them from all the cra-apps where i would like to use them.
@BrunoVanDamme Have a look at #1333 which is for supporting source sharing via monorepo manager (lerna and/or yarn workspace).
I proposed a more generic source-sharing solution in #3436, but it has some downsides vs using a monorepo manager: (1) required some cra-configuration to specify allowable source paths, and (2) managing dependencies of those shared components is a job best left to some monorepo manager anyways...so, my favor has turned more toward using monorepo w/ managers for sharing source between apps. Curious if there's a reason for not using lerna and/or yarn workspace?
As I understand yarn workspaces uses symlinks in the node_modules directory to other locations. My understanding is that CRA does not process files from node_modules, so I would have to do the transpiling on these external components myself. Is this correct? I would expect CRA to process the files symlinked from src as these files appear as if they where in the project itself.
Correct, currently CRA does not process those files, but #1333 tracks the feature request to make CRA process those files.
I think PR 3741 is pretty close to completing that feature, but there are some (minor?) open questions about how it should work. See questions in #1333 (comment) -- any feedback you could provide in that thread would be awesome and helpful in building consensus as to how it should work.
@bradfordlemley Thanks a lot for jumping on that issue btw. I'm sorry repo infra changes are being a bit disruptive right now; hopefully we can review them soon!
I'm using another method to solve the duplicate package problem. Replace @TeemuKoivisto's webpackConfig.resolve.alias line with:
webpackConfig.resolve.modules = webpackConfig.resolve.modules.filter(mod => mod !== "node_modules")
Explanation: CRA configures this modules array to include two entries: node_modules and the full path of ClientApp/node_modules. The line of code above removes node_modules. Now webpack will only resolve modules from your main ClientApp/node_modules folder tree and not from any of your "sibling" shared code projects. This means no duplicated modules, and no need to add modules one by one to your craco config.
Note: You will need to npm install in your main ClientApp the union of all packages you've installed in your shared code projects. (In @TeemuKoivisto's example above, prosemirror-model needs to be installed in the main app even if it is only used in ../editor.) In my project this is just a few packages - YMMV. You can try the config line above and run webpack to immediately see what you need to install.
Note 2: It's important to prevent all module duplication even if it doesn't cause a runtime error, because it can significantly increase the size of your webpack bundle. (You can use source-map-explorer to do a before-and-after comparison.)
@RandScullard hi and no I don't. It works fine with the dependency being just inside editor (which in turn imports another workspace package that uses prosemirror-model). Anyway, installing the deps for the CRA would be even more annoying than just adding aliases so I'll let my hack stand in my repo. But thanks though for the explanation!
Explanation:ForkTsCheckerWebpackPlugin does the TypeScript type checking in the webpack build. The default webpack config sets the reportFiles option for this plugin to filter out errors from anywhere outside the local project1. As a result I did not get any TypeScript compiler errors from my shared project, only from my main project. My solution is just to clear out the reportFiles array so there is no filtering of errors. (This might be too broad a brush for your project and you may find it preferable to modify the array to leave some of the filters in place.)
All this to try to get symlinks to work the way the OS designers intended them to work?
Surely, this needs re-evaluation on the part of CRA? If an application developer is creating symlinks, he/she probably has a good reason - I don't think its right to second guess them.
Reacted by Vicary, romgrk-comparative, Wynn Slater, Chris, Ryan Saunders, Globebyte, Bert Verhelst and Amey
All this to try to get symlinks to work the way the OS designers intended them to work?
FWIW, I used the techniques described in this issue to get my shared module working without symlinks. Rather than symlinking my shared module into my main project, I have it linked in my package.json like so:
Thanks @RandScullard - yes, there are workarounds but they shouldn't really be necessary. I sometimes use a similar workaround to the one you describe but HMR doesn't work; package manager caching gets in the way. I have to delete node_modules and/or clean caches when updating components - all very unproductive.
@hasan-aa I am not using CRA v5, I am still on 4.0.3. I am waiting to upgrade until craco fully supports v5. (dilanx/craco#378)
I have taken a look at the changes to webpack.config.js in CRA v5 and I can tell you that the workarounds above will definitely have to be modified to be compatible with the new config. I believe they still can be made to work, but not exactly as shown above.
It turned out the caching behavior was making it almost impossible to debug. If the previous build was creating duplicate modules, even if you fix the configuration and build again, it was still resolving the wrong modules due to the cache I believe.
Once I enable memory cache, it became debuggable and now it's working fine. config.resolve.cache = true; (memory cache)
By the way, my solution is to move 'node_modules' to second position in the config.resolve.modules array so that the project node_modules folder takes the precedence:
For the ones hoping for a fix for webpack and when you npm link a package you will have to do the following.
It seems like when you have a linked package npm link "myPackage" (you are creating a symlink) this does not get properly resolved by the following line
Add the following code to resolve the symlink to the right path /config/paths.js (the resolveRealPathApp will also work in a production build as it will just get the normal package, and not follow the symlinked one)
Has any progress been made on this issue? I was using symlinks as a way to share interfaces between my Firebase Cloud Functions project and its React frontend project, but was surprised to find that as soon as I added enums everything broke (similar to the issue that @ali-wetrill was having above). Unfortunately, all the workarounds above seem to rely on unmaintained stuff, with react-app-rewired, customize-cra, and craco all not supporting CRA 5.0. If not, does anyone have any alternative suggestions for how to achieve the same thing?
Reacted by e40, Rom Grk, Farsab B, Ignacio Tartavull and Chen Zhutian
Reacted by e40, José Javier Rodríguez Zas (JJ) and Sam Stern
FWIW, I've added a small cp -a ../shared src/ command to all my NPM commands in package.json and added the src/shared under every project to their .gitignore file to work around the issue. From CRA's perspective, it's just a file and you still get to maintain a single copy for multiple projects.
FWIW, I've added a small cp -a ../shared src/ command to all my NPM commands...
I've elaborated on this solution by using watch to monitor the files (the source and destination) and rerun rm -rf and copy commands to sync destination with source if they are changed in either location (rsync is not universally available). I then run this in parallel with react scripts like start and test, which support live loading. This means the live coding aspect is fully inclusive of the shared files and the files are protected from being edited in the wrong place. React picks up the overwriting of the files in destination as file edits and refreshes them as you'd hope.
Activity
Timer commentedon Dec 8, 2017
It sounds like a bug, but this should be working. Can you give more details to reproduce this easily & some test files? A repo with README would be fantastic.
subhero24 commentedon Dec 11, 2017
I created a repo here.
This was just initialisation with CRA under MacOS High Sierra and then symlinking in terminal with:
cd src && ln -s ../symlinkTimer commentedon Dec 11, 2017
Thanks!
nuthinking commentedon Dec 27, 2017
I actually have only problems with Symlinks when building for deployment: #3650
On dev it works well.
bradfordlemley commentedon Jan 11, 2018
@BrunoVanDamme Can you elaborate on your use case? (Is it related to trying to share source between cra-apps and/or monorepo?)
subhero24 commentedon Jan 11, 2018
I am trying to share components between projects, so I would like to have these components in another directory and symlink to them from all the cra-apps where i would like to use them.
bradfordlemley commentedon Jan 11, 2018
@BrunoVanDamme Have a look at #1333 which is for supporting source sharing via monorepo manager (lerna and/or yarn workspace).
I proposed a more generic source-sharing solution in #3436, but it has some downsides vs using a monorepo manager: (1) required some cra-configuration to specify allowable source paths, and (2) managing dependencies of those shared components is a job best left to some monorepo manager anyways...so, my favor has turned more toward using monorepo w/ managers for sharing source between apps. Curious if there's a reason for not using lerna and/or yarn workspace?
subhero24 commentedon Jan 11, 2018
As I understand yarn workspaces uses symlinks in the node_modules directory to other locations. My understanding is that CRA does not process files from node_modules, so I would have to do the transpiling on these external components myself. Is this correct? I would expect CRA to process the files symlinked from src as these files appear as if they where in the project itself.
bradfordlemley commentedon Jan 11, 2018
Correct, currently CRA does not process those files, but #1333 tracks the feature request to make CRA process those files.
I think PR 3741 is pretty close to completing that feature, but there are some (minor?) open questions about how it should work. See questions in #1333 (comment) -- any feedback you could provide in that thread would be awesome and helpful in building consensus as to how it should work.
gaearon commentedon Jan 11, 2018
@bradfordlemley Thanks a lot for jumping on that issue btw. I'm sorry repo infra changes are being a bit disruptive right now; hopefully we can review them soon!
gaearon commentedon Jan 11, 2018
We also merged Jest 22 into
nextbranch so you might want to use that as a base.45 remaining items
RandScullard commentedon Oct 28, 2021
I'm using another method to solve the duplicate package problem. Replace @TeemuKoivisto's webpackConfig.resolve.alias line with:
Explanation: CRA configures this
modulesarray to include two entries:node_modulesand the full path of ClientApp/node_modules. The line of code above removesnode_modules. Now webpack will only resolve modules from your main ClientApp/node_modules folder tree and not from any of your "sibling" shared code projects. This means no duplicated modules, and no need to add modules one by one to your craco config.Note: You will need to npm install in your main ClientApp the union of all packages you've installed in your shared code projects. (In @TeemuKoivisto's example above,
prosemirror-modelneeds to be installed in the main app even if it is only used in../editor.) In my project this is just a few packages - YMMV. You can try the config line above and run webpack to immediately see what you need to install.Note 2: It's important to prevent all module duplication even if it doesn't cause a runtime error, because it can significantly increase the size of your webpack bundle. (You can use
source-map-explorerto do a before-and-after comparison.)TeemuKoivisto commentedon Oct 29, 2021
@RandScullard hi and no I don't. It works fine with the dependency being just inside editor (which in turn imports another workspace package that uses
prosemirror-model). Anyway, installing the deps for the CRA would be even more annoying than just adding aliases so I'll let my hack stand in my repo. But thanks though for the explanation!RandScullard commentedon Dec 22, 2021
I just had to add another thing to my overrideWebpackConfig for my TypeScript project:
Explanation:
ForkTsCheckerWebpackPlugindoes the TypeScript type checking in the webpack build. The default webpack config sets thereportFilesoption for this plugin to filter out errors from anywhere outside the local project1. As a result I did not get any TypeScript compiler errors from my shared project, only from my main project. My solution is just to clear out the reportFiles array so there is no filtering of errors. (This might be too broad a brush for your project and you may find it preferable to modify the array to leave some of the filters in place.)1 This is the default value for reportFiles:
mcqj commentedon Jan 17, 2022
All this to try to get symlinks to work the way the OS designers intended them to work?
Surely, this needs re-evaluation on the part of CRA? If an application developer is creating symlinks, he/she probably has a good reason - I don't think its right to second guess them.
RandScullard commentedon Jan 19, 2022
FWIW, I used the techniques described in this issue to get my shared module working without symlinks. Rather than symlinking my shared module into my main project, I have it linked in my package.json like so:
mcqj commentedon Jan 20, 2022
Thanks @RandScullard - yes, there are workarounds but they shouldn't really be necessary. I sometimes use a similar workaround to the one you describe but HMR doesn't work; package manager caching gets in the way. I have to delete node_modules and/or clean caches when updating components - all very unproductive.
hasan-aa commentedon Feb 2, 2022
Hi @RandScullard,
Just wanted to confirm, are you using CRA v5.0.0?
Since I've upgraded my code to v5.0.0 none of the above workarounds seem to work.
To get rid of the duplicates, I had to remove duplicated packages from the main app and rely on the nested dependencies of linked packages.
RandScullard commentedon Feb 2, 2022
@hasan-aa I am not using CRA v5, I am still on 4.0.3. I am waiting to upgrade until craco fully supports v5. (dilanx/craco#378)
I have taken a look at the changes to webpack.config.js in CRA v5 and I can tell you that the workarounds above will definitely have to be modified to be compatible with the new config. I believe they still can be made to work, but not exactly as shown above.
hasan-aa commentedon Feb 3, 2022
Hi @RandScullard Thanks for the clarification.
It turned out the caching behavior was making it almost impossible to debug. If the previous build was creating duplicate modules, even if you fix the configuration and build again, it was still resolving the wrong modules due to the cache I believe.
Once I enable memory cache, it became debuggable and now it's working fine.
config.resolve.cache = true;(memory cache)By the way, my solution is to move 'node_modules' to second position in the
config.resolve.modulesarray so that the project node_modules folder takes the precedence:before:
after
Alevale commentedon Feb 24, 2022
For the ones hoping for a fix for webpack and when you
npm linka package you will have to do the following.It seems like when you have a linked package
npm link "myPackage"(you are creating a symlink) this does not get properly resolved by the following lineTo fix
npm linkpackages not updating on your main directory you have to do the following:/config/webpack.config.dev.js/config/webpack.config.dev.js/config/paths.js(theresolveRealPathAppwill also work in a production build as it will just get the normal package, and not follow the symlinked one)/config/paths.jsfileCatches:
Verify that you are not ignoring the folders in the
/config/webpackDevServer.config.jsfilejoelwestland commentedon Jun 6, 2022
Has any progress been made on this issue? I was using symlinks as a way to share interfaces between my Firebase Cloud Functions project and its React frontend project, but was surprised to find that as soon as I added enums everything broke (similar to the issue that @ali-wetrill was having above). Unfortunately, all the workarounds above seem to rely on unmaintained stuff, with react-app-rewired, customize-cra, and craco all not supporting CRA 5.0. If not, does anyone have any alternative suggestions for how to achieve the same thing?
e40 commentedon Jul 13, 2022
It's a decades old trick to symlinks to a single source directory for multiple architecture builds. This issue has broken that for me. 👎
muvaf commentedon Nov 26, 2022
FWIW, I've added a small
cp -a ../shared src/command to all my NPM commands inpackage.jsonand added thesrc/sharedunder every project to their.gitignorefile to work around the issue. From CRA's perspective, it's just a file and you still get to maintain a single copy for multiple projects.a-i-joe commentedon Mar 25, 2023
I've elaborated on this solution by using
watchto monitor the files (the source and destination) and rerun rm -rf and copy commands to sync destination with source if they are changed in either location (rsync is not universally available). I then run this in parallel with react scripts likestartandtest, which support live loading. This means the live coding aspect is fully inclusive of the shared files and the files are protected from being edited in the wrong place. React picks up the overwriting of the files in destination as file edits and refreshes them as you'd hope.npm install --save-dev watchThis is what my script look like:
run-sandrun-pcome fromnpm install --save-dev npm-run-allI don't recommend trying to re-use the
"sync-shared"script from"watch-shared", because running a node script in fromwatchmay restart everything.raymi commentedon Apr 2, 2023
On linux-like systems you might also be able to use
mount --bindinstead of copy & watch to link your shared directory.