I was going through the React codebase, and I noticed how React's require doesn't quite behave like in Nodejs. I don't get what's going on here.
Looking at line 19 on ReactClass.js for instance, there's a require('emptyObject'), but emptyObject isn't listed in package.json, nor does it say anywhere where that module's coming from.
https://github.com/facebook/react/blob/master/src/isomorphic/classic/class/ReactClass.js#L19
I did find "emptyObject" on npmjs, but the API there seems different from the one used in React; the .isEmpty grepped in React isn't related to emptyObject.
So where is emptyObject getting loaded from, and how is React's require doing what it's doing? This is not intuitive. At all.
The location of the emptyObject module which React refers to is https://github.com/facebook/fbjs/blob/master/packages/fbjs/src/core/emptyObject.js#L9 Note that it doesn't follow the CommonJS module system.
To make it easier for Facebook to share and consume our own JavaScript. Primarily this will allow us to ship code without worrying too much about where it lives, keeping with the spirit of #providesModule but working in the broader JavaScript ecosystem.
From https://github.com/facebook/fbjs#purpose
The way of defining a module by adding #providesModule in the license header and loading those modules with require in Node is called Haste, a customized module system built for Facebook's open source projects.
In fact, unless you would like to understand the inner workings of React or contribute to Facebook's open source projects, you don't need to know that. In other words, it's not recommended to use Haste to write your own project.
Along the same lines, the invariant module being loaded at line 10 of ReactClass.js is declared at https://github.com/facebook/fbjs/blob/master/packages/fbjs/src/__forks__/invariant.js#L9
As far as I know, both Eclipse and WebStorm don't support Haste so IDE can't help. But with Haste, the name of file and module should be the same, so you can find a module by searching for the filename, i.e. double shift in Webstorm and Ctrl+Shift+r in Eclipse. However, the emptyObject you asked about or invariant are not part of React so it's still cumbersome to find their origin.
Otherwise, there is a team that shares and organizes what they learn from hacking React that I contribute to occasionally and they have linked those requires by following Haste to the corresponding origin file e.g. https://annot.io/github.com/facebook/react/blob/cc3dc21/src/isomorphic/classic/class/ReactClass.js?l=19 You may want to see that.
I noticed how React's require doesn't quite behave like in Nodejs.
Right. Facebook has its own module loader. All modules have unique identifiers, provided by the #providesModule directive in each module. This allows you to use the identifier to load the module, instead of the file path.
Of course that doesn't work in a Node.js based environment. So when React or any other Facebook project is published to npm, all require calls are rewritten automatically to something that Node understands.
This functionality is provided by fbjs which contains shared dependencies and build helpers for all Facebook projects. This is where you find the emptyObject module.
If you look at React's gulp file, you can see how the module maps are constructed and that a custom Babel plugin is used to convert all require calls.
Related
I am used to simply using process.cwd() directly inside of node applications, however, I have recently read the node docs and saw that it recommends importing it from node:process.
So what is the difference from just calling it directly?
process.cwd()
vs importing it and calling it:
import {cwd} from 'node:process'
cwd()
I am currently building a CLI application in case that makes a difference.
Is there a difference?
Which one should I be using?
importing it from node:process guarentees that you get the built-in process module, not some global that some other code in the project has configured or overridden.
This may be done for safety reasons or just for robustness reasons so other modules in the project can't hack on a global process object before you get to use it.
It also may not normally be needed, but is considered good project hygiene as it deters certain types of hacking.
I have started to learn react and I am very confused with the concept of packages.
and why we can't just use a simple link as cdn and there is a module which i don't understand it and what's npm and why i have to use it with react
Not trying to give the definite answer here, but trying to explain the 3 terms as simple as I can:
A module is just a file containing lines of JavaScript code.
A library uses one or many modules to provide a set of features.
A package is a downloadable, versioned library. Think of someone putting it in a box and shipping it to you, so you can import it and use it in combination with your own code.
so I came with conclusion and hope you tell me if I get it right or not .
-Module : it is justba javascript file but it's different from normal script that it has its own scope so you have to use import or export to exchange information between modules.
-Library : it is a group of modules or scripts that it is responsible for the function you want .
-package : can be one or more libraries but it is also contain files that don't deal with the functionality but it's only role to make sure the libraries and functional file work properly .
like react package it is come with react library deals with the functionality and also has babel compiler to make browser read and understand react library.
It is very much possible to use a simple link such as a CDN. Many packages also have links available, such as material UI. However, it quickly becomes unmanageable to use CDN links when your project grows, and it can affect performance and load times of your site.
Npm stands for Node package manager. It handles packaging for Node, where it would not be suitable to use a simple link.
It turns out that it is possible to also use npm for web applications, by combining it with a bundler. The bundler (such as webpack) takes all of your modules (JavaScript files and npm packages) and bundles it together so that you get a single script which you can run in the browser.
I wrote a clojurescript project. It is a reagent component. Now i want to use this component in other clojurescript project. That is what i do: I compiled my cljs project and then i put a result compiled file to js folder in other project. Further i require that file from index.html. At the end i invoke my component from cljs file
(.slider-view (.-views js/swipe) (clj->js [[:p "1"]
[:p "2"]
[:p "3"]]))
and it works. But i have a question. My project and project where i connect my component have common requirements. For example React and ReactDOM. How to exclude this two references from my project and then connect it from another project? Is there alternative approaches? For example require cljs namespace from another cljs project directly
Even if you could prevent JavaScript libraries from being included twice, you will still have huge chunks of the ClojureScript standard library compiled in twice. As you suggested, you will want to put your first project on the classpath of your second project (by adding it to your project.clj or equivalent) and then include that namespace directly.
Building on Justin's quite correct answer...
What you describe is exactly the normal ClojureScript dependency relationship. In this case, the dependency is something you have created, rather than someone else's existing library, but it is still the same situation.
There is one important subtlety to note. You may want to develop both of your projects simultaneously. This may seem tricky, since dependencies normally require a version number, deploying, and all the rest of the heavy lifting that is just too painful for quick development.
Fortunately, the standard ClojureScript tooling offers a solution to this, called the Leiningen checkouts directory, which works by letting you put a symlink to your dependency inside your main project's directory.
Details are in the checkout-dependencies section of the Leiningen documentation; or just web search for "Clojure checkouts", if that ever decays.
As you get further into these techniques, you may hit some more subtle problems involving the Figwheel tooling. When you reach that stage, this article may also be useful.
I imagine this problem would apply to other frameworks that have a bit of a plugin/component ecosystem about them that rely on specific build tools (React components with JSX, etc). Vue is just my use-case.
I have authored several Vue components in the form of single .vue files which are published to NPM. The package.json for these component does not list any dependencies, as they themselves are intended to function within a parent project that uses webpack, vue-loader, sass-loader, etc. This is an example of one such component.
I am unsure about the best way to declare that these components rely on the parent package having said build tools. I am not confident that devDependencies is the correct place for them as the component itself has no development step that relies on these. peerDependencies seems more suitable but again I am not confident this properly matches what I am trying to achieve.
Looking through many of the components on the awesome-vue repository I can't see any use of peerDependencies and the devDependencies seem relevant to the development of the particular components themselves.
What is the correct way to author these components? It's almost like I need something like "peerDevDependencies".
Most component are, unfortunately distributed already compiled.
In my opinion the best way to distribute a component is to write as main the raw .vue file of the component.
You shouldn’t specify to use any particular tool, developers that pick up your package should be free to use the tool they want, be it Browserify or Rollup (or Webpack). The raw .vue format allows them to compile the .vue component with whatever tool they want and using whatever Vue version they want (within a range of course).
Moreover what I like to do is give the users the possibility to use the component straight away, even inside a browser, with just Vue as a <script> dependency. For this you would have to compile it and, yes, specify Vue as a peerDependency in the sense that it’s needed in the page.
You can put meta information in the package.json to tell CDN to pick up the compiled version when inside the browser, this is very handy so the user just specify the name of the package without worrying about the file name or version.
Speaking only as a consumer of Vue.js components, I think specifying your build dependencies as peerDependencies is the best solution. You are using what is a pretty standard build pipeline, but I think that having them specified is important. These are not strictly devDependencies or dependencies depending on where they are going to be compiled by the end user.
I'd suggest you use "module" property on the package.json for the raw vue file, and the "main" as the compiled one. module is a property getting standardized and webpack and rollup already understand it.
For more info see setting up multiplatform npm packages article.
While trying to use this library
I initially got error ReferenceError: require is not defined.
To solve it, I added required library. This now started with another error as Module name "crypto" has not been loaded yet for context
FOR LEG PULLERS: This is not a duplicate question, As all the questions are either poorly answered or not answered.
I have done my research, EG: this does not tells where to try it.
this is unanswered. this does not tells where do I get those paths like 'path/to/filesize' and all other paths anyways if I get then also is useless in my context. this defines a module of its own, I need a predefined "crypto" module. The default google library is not doing the job.
From my guessing, you are under browser environment instead of developing a NodeJS app.
This crypto you refer to is actually for back-end (NodeJS), provided as NodeJS API, and also, the require keyword, is a NodeJS one.
And from my knowledge, there is no crypto in the default browser environment, neither is there a require. For most cases, there is a REQUIRE.JS and Browserify that let you use this type of require statement, but for your case, I suggest not to use them.
For crypto used in browser environment, I would suggest something using some third-party libraries, like crypto-js, and you without browserify or bower, you should pay special attention to its Usage without RequireJS section.