I just figured out that I have circular dependencies in my modules. (cjsx stands for Coffee+JSX)
I have a file index.cjsxwhich contains the following:
modules =
App: require('./App')
Code: require('../../components/elements/code/Code')
Icon: require('./icon/Icon')
Page: require('./page/Page')
Toolbar: require('./toolbar/Toolbar')
Toolbars: require('./toolbar/Toolbars')
Wysiwyg: require('./wysiwyg/Wysiwyg')
console.log modules
module.exports = modules
Then, on my application, I use the following syntax:
{ Icon, Toolbar, Toolbars } = require '../index'
The index.cjsx is here just to allow this syntax and avoid to require each module separately.
But now I'm facing the issue where my App component requires the index file, and my index file requires App. There is a circular dependency. It's not causing a bug by itself but things get complicated at some point because now, when I require index in some component, I only get an empty object {}.
When I add logs in Wysiwyg, I see the following:
script.js:197 Object {}// The object is empty, console.log require '../index' (in Wysiwyg)
script.js:90 Object {App: Object}// The object is not empty here and contains everything I need. (console.log modules, in index.cjsx)
script.js:209 undefined undefined
script.js:45151 Warning: React.createElement: type should not be null, undefined, boolean, or number. It should be a string (for DOM elements) or a ReactClass (for composite components). Check the render method of `Wysiwyg`.
It looks like my index is actually loaded after it has been required.
I wonder if I can do something to fix this or if I must require each package separately from the component itself. Thanks for input :)
I fixed the issue by not requiring index from the App component (which is the master and is at the root directory. And by not listing the App component in the index file.
you should use index.js file to require only the files in the current folder. this way you avoid circular dependencies if you manage your folders right. In your example, you would add an index.cjsx in the folder toolbar for example with just Toolbar and Toolbars and then to
{ Toolbar, Toolbars } = require './toolbar'
Note: you can omit the index file, it is assumed if you put a folder path
Related
How can I use monaco in my electron app? out this example: What's the proper way to do that? i'm open to new suggestions. I throughout into building a micro frontends but it's not that nice in react/electron and in the end i would have to include the final index output file using iframe. I wish I could use something we do with dlls in desktop application. note: i'm new to react and electron, perdon mystakes that seems so simple.
Well, I tried to "merge" as needed both webpack configs. Is this the way to go? so far i couldn't make it. I added:
resolve: {
alias: {
'vscode': require.resolve('#codingame/monaco-languageclient/lib/vscode-compatibility')
}
but it cannot find the vscode module, i'm getting the error:
Module not found: Can't resolve 'vscode' in 'C:\Users\jjj\Desktop\merge\Newton\node_modules\vscode-languageclient\lib\common' even tho the package is installed.
I also tried to add "editor.worker": 'monaco-editor/esm/vs/editor/editor.worker.js' in the entry section but I got the error:
An unhandled error has occurred inside Forge:
Conflict: Multiple chunks emit assets to the same filename index.js (chunks 179 and 915)
Error: Conflict: Multiple chunks emit assets to the same filename index.js (chunks 179 and 915)
I did plan to -- assuming it's the proper way to go ---, once managed to fix this webpackes merge, I'd include the main file with the contents:
require('monaco-editor');
(self as any).MonacoEnvironment = {
getWorkerUrl: () => './editor.worker.bundle.js'
}
require('./client');
then have
<div id="container" style="width:800px;height:600px;border:1px solid grey"></div>
somewhere to show the editor and the <script src="main.bundle.js"></script> wouldn't be needed due to the fact it would be included in the webscript's output javascript bundle file, used elsewhere by the entire application.
Various errors may occur depending on the bundler configuration, so I made it simple example by referring to codes monaco-editor and monaco-languageclient. Both repositories work after build, so I separated the main process and renderer process folders to avoid overlapping outputs. Maybe this is related to Forge's error.
I created an Electron renderer code using monaco-languageclient's client code, and in the main process, run monaco-languageclient's server. Therefore, both processes must share the same web socket port. You can also erase the following lines and run LanguageServer externally.
Here is an example without the iframe.
I am working with mongoose.js (~4.6.1), node / express and exporting a model.
When I require the model, it works in 99% of the app. However, there are a few files and directories (even some at the same level) that do not receive the proper value when I require the model, it is an empty object.
Furthermore, if I use the:
mongoose.model.('name-of-model').find approach, I get the error, MissingSchemaError: Schema hasn't been registered for model
I tried requiring the model into these files and wrapped a console.log in a setTimeout thinking it was an async issue, but the object is still empty.
Here is my problem:
When requiring a module, it works in a few files at the same level in the directory tree, but fails to import (require) the same values in files with the same exact relative path needed to access the module. Is it possible to block requiring modules into specific files?
I also tried a few steps to see if it is a circular dependency problem after reading this thread but this doesn't seem to be the problem.
I have two js files on my node server that require each other.
both have objects that are exposed via the module.exports mechanism.
1st file is located under bl/commands.js and uses:
var smUtil = require('./../utils/smUtil');
2nd file is located under utils/smUtil.js and uses:
var commands = require('./../bl/commands');
When a function runs from smUtil.js and uses some properties of commands.js it seems like command is an empty object and the import was not successful.
Here is the catch, when i remove the require of smUtil form inside commands.js everything works, which makes me think that i'm doing a newbe mistake.
Any thoughts?
Node.js documentation about circular dependencies
You are absolutely right that empty objects are returned.
To Quote Node.js documentation
When main.js loads a.js, then a.js in turn loads b.js. At that point, b.js tries to load a.js. In order to prevent an infinite loop, an unfinished copy of the a.js exports object is returned to the b.js module. b.js then finishes loading, and its exports object is provided to the a.js module.
A solution could be to create a separate file to require both the files there and instantiate that file to avoid the circular dependency.
The specific solution which solved my problem was to place var smUtil = require('./../utils/smUtil'); Underneath the module.exports inside commands.js.
However i feel like this solution is not the best one out there.
Thanks to the author of:
coderwall.com/p/myzvmg/circular-dependencies-in-node-js
I get the following error when trying to do server-side rendering with components that reference window. For example when I include slick-carousel (https://github.com/kenwheeler/slick) I get the following error:
var Slick = window.Slick || {};
^
ReferenceError: window is not defined
I know its because window is not defined when trying to do SSR, but don't know what the best strategy is to avoid the error.
Basically components should not depend on DOM. Only, some hook methods such as componentDidMount can, where you use .offsetHeight and modify style or whatever. That's why react and react-dom packages are separated.
Instead of passing object by window.XXX, think about using decent dependency solution like require.
Experimenting with a bootstrapped extension, I'm trying to understand the scopes and/or persistence of jsm modules by setting a property, called baseUri, on a module object from bootstrap.js and reading it again from javascript in my options.xul (which is opened from the Add-ons Manager).
My current understanding is that JavaScript Code Modules are persisted, once loaded. However, when I try to access baseUri from options.xul, its value is undefined.
install.rdf:
<!-- just the relevant XML (this works as expected, by the way): -->
<em:optionsURL>chrome://test/content/options.xul</em:optionsURL>
/modules/Test.jsm:
var EXPORTED_SYMBOLS = [ 'Test' ];
Test = {
baseUri: undefined
}
/bootstrap.js:
// this is done in global scope,
// not inside install() or startup() for instance, if that matters
let test = Components.utils.import( 'file:///absolute/path/to/Test.jsm', {} ).Test;
test.baseUri = someBaseUriIExtracted;
/chrome/content/options.js (included in /chrome/content/options.xul):
let test = Components.utils.import( 'file:///absolute/path/to/Test.jsm', {} ).Test;
console.log( test.baseUri ); // undefined
So, I guess what I'm failing to fully understand is what the exact scopes are from which I should be able to access object properties from exported jsm symbols and/or how and when exactly these objects are persisted.
Does my problem have anything to do with sand-boxing, perhaps? Does Firefox consider options.xul, when opened from the Add-ons Manager, to be a different security scope than bootstrap.js, perhaps?
Can you shed a thorough light on the actual scopes of jsm modules and when and where I should be able to access persisted properties on jsm modules?
The documentation is pretty straightforward about what and how is shared
Each scope that imports a module receives a by-value copy of the
exported symbols in that module. Changes to the symbol's value will
not propagate to other scopes (though an object's properties will be
manipulated by reference).
I think the accompanying examples are clear.
Maybe you should use getters/setters.
From what I know:
Other jsm modules
Browser window
Content window
bootstrap addon scope