I just wondering let's say I already have a website. If I would like to inject some react modules into it lets say MODULE-A, MODULE-B, MODULE-C. At some situations, MODULE-A and MODULE-B are on the same page. All modules are sharing react, axios but also they have their own dependencies. what is actually the best approach to prepare build for it?? I actually like create-react-app. Is there any smart way to make modules only load required dependencies? so I can include them separately and if both exist on the page they will not clone dependency in code.
I want to avoid the situation that I have 20 small modules and all of them use react inside built code. So 60% of the code will be duplicated dependencies.
You have not many options
You can leverage code-splitting as referred here https://webpack.js.org/guides/code-splitting/ so let's say you have
ModuleA -> [depA, depB, depC]
ModuleB -> [depA]
ModuleC -> [depC]
now you can code split to 4 javascript files which will be
moduleAbundle.js
mobuleBbundle.js
mobuleCbundle.js
vendors.js
vedors will be concatenation of depA, depB, depC but ofcourse when you will load moduleB and ModuleC on 1 page you will be also loading depB as it's included in vendors.js you will need to think and play a lot with orchestration of this.
But what you can actually do you can think of most critical parts and most shared deps and list them, let's say all of your packages are using react, react-dom, lodash you will make bundle for vendors with only those libraries, any other library will be bundled with module itself and yes you can't 100% elimate "double-loading" but if you will double load library which has several kB it's fine, when it's larger, ship it with vendors.js
or you can have some complex mechanism on backend side when you will exactly specify and orchestrate loaded dependencies because you know which modules are rendered and what are they dependencies. But there are no any ways of on-the-fly bundling and sending only needed and requested dependencies, it would be very slow to do that on-the-fly and you need to flush quick response to the browser not slow it down with additional compilation process. So it's most likely a manual job to correctly prepare and split code in logical chunks which makes sense.
I dont know answer for React but for the future, maybe you can think about using Angular instead, and its ngModule capability into splitting application to multiple independent modules with their own dependences.
https://angular.io/guide/ngmodules
Related
I've been tasked with the development of a NPM package with a custom component (in this case a react component) that makes uses of other dependencies such as plate, slate, etc.
I'm in the process of preparing the output dist but it's not clear to me what the best practices are when doing so:
Should all dependencies be resolved and bundled into a big .js file or this can be ignored ? (I'm using rollup resolve here). I'm afraid this would produce a huge file including the source of all the dependencies but as I stated I'm really not familiar with the process...
In the other hand, is it common NOT to resolve such dependencies and let the final consumer of the component do so ? (I'm only assuming here)
It's all about pros and cons... and what is possible. For example React itself can only exist in one version in an entire project so you should never include that.
Dependencies that are needed but not included should be added as peerDependencies in your package.json and it is the responsibility of the consumer to download them. The downside with including dependencies (as dependencies so that they will be downloaded automatically by the consumer) is that the bundle of the consumer might be bigger than it needs to be. Here you should take into account who will consume it; is it for internal use in your organization or public use? Do you know anything about the context it will be used in? It's best not to include dependencies since it will contribute to smaller resulting bundle for the consumer but if it's unlikely that the depending dependencies are present in the build environment of the consumer, you might as well add it to your package. The situation that you want to avoid is that your package includes a different version of the same package that the consumer is already using; then the resulting bundle may contain two versions of a lot of code that could potentially be reduced to one version (if the version used by the consumer and by your package are compatible). Of course all of this potentially becomes worse and more likely with large common dependencies than with small uncommon dependencies.
An example: in my organization we use Material-UI. We have a package with React components using Material-UI which we consume in other projects. Since Material-UI will always be present in the projects, it's bad practice to include it in the package, even though it will place a higher responsibility on the consumers (us) to align different versions of the package with whatever version of Material-UI that we're using in the applicable project. Given another consumption context, including it in the package might have made more sense.
According to me, you should never bundle your package since it makes tree shaking more complicated for the consumer. This applies to esm packages (cjs is not tree-shakeable). In cjs on the other hand it's devastating with bundled packages since it prevents the consumer from making more specific imports to avoid importing a lot of unused code, e.g.
import Comp from "package/Component"
instead of
import { Comp } from "package"
There's almost never a good reason to embed dependencies inside library bundles. That's how you end up with multiple copies of dependencies in web apps. At best, web apps' bundles end up being unnecessarily bloated. At worst, dependencies that break when they're duplicated (e.g. React) yield all sorts of unexpected behaviour.
The surefire way to prevent dependency duplication is to avoid bundling libraries at all. If you inspect your node_modules folder in any of your web app projects, you'll likely find numerous third-party dependencies that aren't bundled. And their lack of bundling doesn't have an impact on your web app. That proves that library bundling is pointless.
I'm working on an old Codeigniter website where the Javascript codebase is messy and poorly structured and I would like to use Webback to manage the scripts. My goal would be start using it to bundle the code I have the way it is, and gradually refactoring it to make use of modules and imports.
At the moment I'm using Gulp on development (but mostly to minify the files) and Carabiner (a Codeigniter library) to insert the scripts in the views.
The scripts, which are all written as IIFEs are not bundled, so in every controller function I have an array of the scripts needed in that page. For example:
public function homepage()
{
$this->carabiner->js([
['libraryThatIOnlyNeedHere.min.js'],
['myscript1.js'],
['myscript2.js'],
['myscript3.js'],
]);
I would like to use Webpack to create a series of bundles so that I end up loading maximum two files on every page: one for the libraries and one for my scripts.
All the practical examples I've seen with Webpack, though, are for Single Page Applications where it's quite easy to bundle everything together.
What would be the best approach in my case? Considering that the code is still not ready to properly use modules and imports, shall I create many entry points in the Webpack configuration file, possibly one for every page and list every script needed in that page?
Main idea behind webpack is to build modules graph from provided sources and then to combine it into bundles. If your code doesn't have explicit dependencies - it may be good idea to start with creating a module from every file using any of available approaches (AMD, CommonJS, etc). You will need to create module identifiers and define dependencies for every module. It may be worth to read this article for example.
As intermediate step you may want to use some loader like Require.JS to load your modularized code.
Until this step will be done - there is not much use of Webpack.
I have a production application whose folder structure is much like you would expect:
/project
/css
/js
/php
/fonts
/images
/index.php
I have recently begun learning to use react.js and I would like to start developing new features using react while leaving all existing functionality as is and I understand that react.js can certainly be used this way.
What isn't entirely clear, is how to structure the files in my non node.js project and access them.
For example, I tried searching for this and found this article which proposes the following structure
and states:
Here index.jsx works as the entry point of the application. It uses ReactDOM.render to render App and gets the party started. App in turn does something interesting with Note. If I wanted yet another component, you would simply add it below /components.
Presumably this is a node.js project where index.jsx can call something like require('components/App.jsx');, but how do I achieve the same in my non node.js project.
Consider if I set the following folder structure:
/project
/css
/js
/php
/fonts
/images
/react
/components
/App.jsx
/Note.jsx
/scripts
/featureFoo.jsx
/index.php
Given the above, I'd like to have index.php load react/scripts/featureFoo.jsx which would somehow include/use react/components/App.jsx and react/components/Note.jsx
I figure I could have script tags in index.php to load all of the components then featureFoo.jsx but I feel like there is a more react way to do this.
So
How can I structure/access the react components of my non node.js application?
Im tagging node.js as I feel those users may well bring insight regarding this possibly from having to deal with multiple projects/aproaches.
In order to import/require other modules in a non-node.js (i.e. browser-based) JS application, you'll need to use a bundler such as webpack or browserify.
They work by starting at your "entry" file (index.jsx in your case) and recursively following all of your imports/requires. Then it smartly bundles everything up into a single "output" file, which includes everything your application uses, that you can link in your HTML.
You can also use more complex configurations with multiple entry and output files, or even dynamic loading of "chunks" at certain points in your application. But the above is the most basic use case, and works well for most simpler projects.
These bundlers have some other cool features as well. For instance, with webpack (with additional plugins and loaders) you can:
Write ES6/ES7 JavaScript that gets compiled (via babel) into cross-browser compatible ES5
minify/uglify your output JS
import/require non-js files such as CSS, images, and webfonts, and choose how to process these imports (e.g. pre/post-process your CSS, or optimize your images)
Extract all imported CSS into a single .css file
Use webpack-dev-server (or webpack-dev-middleware) to take advantage of hot module replacement, which makes developing JS apps easier by letting you see your changes take effect instantly in the browser without having to refresh or lose your app's state.
And a lot more. The world of bundlers is a pretty big ecosystem with a lot to learn, but it's totally worth getting into.
A good place to get started is the excellent Survive JS series of tutorials.
However, if you're still learning React, then diving into webpack and the entire ecosystem of JavaScript tooling can be overwhelming. It will probably be easier and a more efficient use of your time to keep things simple at first, and then only get into bundlers etc. after you get comfortable with React.
Webpack makes it really easy to bundle things together, and also asynchronously requiring single chunks.
However I can't quite work out how to delay requiring a set of dependencies needed by only a few parts of my app.
Since it's an SPA, I'd like to avoid using a <script> tag and have it load a set of larger (namely brace, esprima, lodash etc) dependencies when the user reaches the relevant parts of the app.
This is similar to the vendor split approach, except I only need the essential modules for navigation, signup, login etc. When using chunks out the box it duplicates these dependencies for each chunk, so they are common dependencies - but I'd like to have more than one common bundle; and be able to load it asynchronously when needed.
This is called code splitting. (Webpack Code Splitting) Take a look at the Webpack site for a "brief" breakdown of how it works. Most of the tutorials out there reference code splitting for critical path rendering, but the concept is the same and should be applicable for your situation.
I would recommend creating an entry for the your dependency bundles, and then reference that withing each module. While you should theoretically be able to just pull in dependencies for each module independent of the "bundled dependencies", I have ran into issues with webpack where dependencies are reinitialized when referenced by separate bundles, which causes issues for dependencies that are meant to be singletons.
I've read a lot of articles on AMD solutions like RequireJS or module loaders that follow CommonJS style in Javascript.
Let's say I have an app splitted in this parts:
App definition that rely on the framework i use
Model 1 that rely on App definition and framework
Model 2 that rely on App definition, Model 1 and my framework
I may write each part as a RequireJS module or a common JS module and split my project in how many files I want but what's the advantage of writing each part as a module or splitting them in many files and then load them in the right order (to avoid dependency problems) maybe concatenatening all the files in a big one to reduce HTTP requets (as done by r.js optimizer)?
In my opinion, there are three rather important reasons:
You can create and re-use modules without polluting the global namespace. The more polluted your global namespace is, the bigger the chance of a function/variable collision. That means you define a function called "foo" and another developer defines the function "foo" = one of the functions gets overwritten.
You can structure your code into separate folders and files and requirejs will load them asynchronously when needed, so everything just works.
You can build for production. RequireJS comes with its own build tool called R.JS that will concat and uglify your javascript modules into a single (or multiple) packages. This will improve your page speed as the user will have to make less script calls and load less content (as your JS is uglified).
You can take a look at this simple demo project: https://c9.io/peeter-tomberg/requirejs (in cloud9ide).
To build your modules into a single app, all you have to do is have requirejs npm package installed and run the command: r.js -o build/build.properties.js
If there are any questions, ask away.
Edit:
In development, having all modules in separate files is just a good way to structure and manage your code. It also helps you in debugging (e.g. error on "Module.js line 17" instead of "scripts.js line 5373").
For production, you should use the build tool to concat and uglify the javascript into a single file. This will help the page load quicker as you are making less requests. Every request you make to load something slows down your page. The slower your page, the less points Google gives you. The slower the page, the more frustrated your users will be. The slower your page, the less sales you will get.
If you wish to read more about web page performance, look at http://developer.yahoo.com/performance/rules.html