Does webpack code splitting work in react-native? - javascript

I am using in a web application react-router.
When using import 'lodash' I import the whole lodash lib in my project.
Code splitting is about using an async import using import().then() to dynamically load chunk while the application is running.
Read about code splitting in react-router/web.
For example: function atRuntime() { import('lodash').then(() => {});}
This will import the library at runtime with an ajax request so it is not bundled in the main.js.
I'd like to recycle my code between web and native and we use a lot of code splitting for each page change.
My app has two main parts and some user will only visit one part so they don't need all user authenticated part.
I expect to be able to use tree shaking during react-native, but it is missing in react-router/native documentation.
What's react-native opinion about code splitting?

if you want to use webpack, you can try with haul https://github.com/callstack/haul
but i highly recommend this implementation without webpack -> https://www.npmjs.com/package/react-native-bundle-splitter

Related

Replacing resource import from old library by import from new library

I had run into a problem in my javascript project. I was using a resource from a library in my project, and I need to replace all instances of it by a resource of the same name, but from another library. The problem is that I'm importing this resource in more than a hundred files alongisde other resources.
What I need is to replace all instances of something that looks like this:
import {someResource, changedResource, anotherResource} from 'old-library'
By this:
import {someResource, anotherResource} from 'old-library'
import {changedResource} from 'new-library'
I need to keep the old imports that includes this resource that I want to get from the new library as well as importing the changed resource from the new library. Is that a way I can do that in Visual Code or I'll need to use some script in order to do that?
right click project root folder ---> find in folder ---> expand the filter
for every "import {someResource, anotherResource} from 'old-library'" you should replace with "import {someResource, anotherResource} from 'old-library'
import {changedResource} from 'new-library'"
example
becomes

Implement static data assets in NPM module for browser use

I am making a small NPM package which would essentially serve as a convenient data import in a React app. My package currently has one exported method, getSystems(), which returns an array of objects. The module code reads the data file using fs/promises.readFileSync which obviously is not available in a browser environment.
How can I bundle the data in my package so that it can be used in a React app?
Here is what the module is doing:
import { decode } from "#msgpack/msgpack";
import { readFileSync } from "fs";
import path from "path";
const file = readFileSync(path.join(__dirname, "../assets/systems.dat"));
const systems = decode(file);
export const getSystems = () => systems;
This works in node. I suppose what I need is a way to configure the build in such a way that the data is included in the output JS files.
Full code here.
Disclaimer'ish: I understand this is usually done via an API instead of bloating the application code with data (which is what I'm doing here, I suppose). This is kind of a learning and testing thing. And also I got sick of copying data files around in Dockerfiles.. :)
Turns out if I use JSON files as source and just import them, the module works in browsers. While the webpack bundle gets pretty big, gzip appears to do a great job compressing the embedded data, so I guess this is the way to go.

How to import simple JS scripts "globally", using ES6 import or require?

I need to assimilate some code into a React app. Problem is, that the code i want to use comes from some example i found on the web, which uses "normal" tags to import various other scripts, via an HTML file.
The main script file that i want to use calls countless various functions from external scripts.(The script "assumes" those functions are available). This of course works in the browser, but not in a build system like Babel/Webpack.
To make things short: what would be the node/es6 equivalent of:
<script src="/dev/getHTMLMediaElement.js"></script>
And how do i make those functions available anywhere in the React app?
My React app is a fairly standard one, booted with react-create-app.
You can require or import this file directly after adding externals option in webpack config
Ref: https://webpack.js.org/configuration/externals/

Attempted import errors in react-native-web monorepo architecture

Hi there,
I am following this article to setup a react-native + web code sharing. Here is the repo link with bare-bone monorepo setup as described in above article.
I successfully did setup bare-bone monorepo app as described in above article, than i ported my existing react-native app code to this architecture(in the components folder) and got mobile app working and everything.
I am getting some errors when i try to run web app(which used react-native-web to convert react-native to web). Its not that i was not expecting some errors, i know react-native-web is yet not that stable and not that up to date for react-native version above 0.55 and all those gotchas.
But the errors i am getting here are more related to my webpack config i think. My config-override.js file is basically the same as original one except this part(which i changed in a hope to get through the errors i will mention below):
const appIncludes = [
resolveApp('src'),
resolveApp('../components/src'),
resolveApp('../../node_modules/react-navigation-deprecated-tab-navigator'),
resolveApp('../../node_modules/react-native-color-matrix-image-filters'),
resolveApp('../../node_modules/react-native-htmlview'),
resolveApp('../../node_modules/react-native-loading-spinner-overlay'),
resolveApp('../../node_modules/#react-native-community/async-storage'),
resolveApp('../../node_modules/react-native-cookies'),
resolveApp('../../node_modules/react-native-router-flux'),
resolveApp('../../node_modules/react-native-actionsheet'),
resolveApp('../../node_modules/react-native-autocomplete-input'),
resolveApp('../../node_modules/react-native-circular-progress'),
resolveApp('../../node_modules/react-native-google-places-autocomplete'),
resolveApp('../../node_modules/react-native-image-progress'),
resolveApp('../../node_modules/react-native-image-zoom-viewer'),
resolveApp('../../node_modules/react-native-image-pan-zoom'),
resolveApp('../../node_modules/react-native-keyboard-aware-scroll-view'),
resolveApp('../../node_modules/react-native-linear-gradient'),
resolveApp('../../node_modules/react-native-permissions'),
resolveApp('../../node_modules/react-native-phone-input'),
resolveApp('../../node_modules/react-native-picker-select'),
resolveApp('../../node_modules/react-native-progress'),
resolveApp('../../node_modules/react-native-push-notification'),
resolveApp('../../node_modules/react-native-snap-carousel'),
resolveApp('../../node_modules/react-native-svg'),
resolveApp('../../node_modules/react-native-tab-view'),
resolveApp('../../node_modules/react-navigation-drawer'),
resolveApp('../../node_modules/react-navigation-stack'),
resolveApp('../../node_modules/react-native-screens'),
resolveApp('../../node_modules/react-navigation-tabs'),
resolveApp('../../node_modules/#react-navigation'),
resolveApp('../../node_modules/react-native-router-flux'),
resolveApp('../../node_modules/react-native-gesture-handler'),
resolveApp('../../node_modules/react-navigation'),
]
Couple or errors i am getting on yarn workspace web start are:
import {
Grayscale
} from 'react-native-color-matrix-image-filters';
It gives:
Attempted import error: 'Grayscale' is not exported from
'react-native-color-matrix-image-filters'.
If i just remove this import and its use, i than get:
Attempted import error: 'react-native-cookies' does not contain a
default export (imported as 'CookieManager').
On:
import CookieManager from 'react-native-cookies';
While playing around, i also got:
...../node_modules/react-native-router-flux/src/navigationStore.js
Attempted import error: 'TabBarBottom' is not exported from 'react-navigation-deprecated-tab-navigator' (imported as 'DEPRECATED_TabBarBottom').
I am pretty sure this is something wrong with my webpack/babel config(config-override.js file). And i certainly know i will get more errors after resolving these. And this setup might end up not working at all for us. But it worths a try and i must be able to get through these errors with your help.
Thanks.
You can probably not use these packages on the web since they're react native packages (Android and iOS) and not web packages.
Which means that you have to split the files that import and use these packages.
Example of creating a wrapper for CookieManager: cookieManagerWrapper.js(everything else: Android and iOS) and cookieManagerWrapper.web.js(Web only).
In the web specific js file, you don't import CookieManager but import an alternative web library instead to implement the same functionality as on mobile but with different code that works on the web.
Then you can import and use cookieManagerWrapper.js everywhere and react-native-web will automatically substitute it with the cookieManagerWrapper.web.js when available.
Some react native packages do work on web too when they're only consisting of platform independent JavaScript code. Also some packages have web implementations that can be aliased in webpack like react-native-gradients with react-native-web-gradients, sadly this is not the case with the packages mentioned in the question.
This file splitting with file.js, file.web.js, file.android.js and file.ios.js makes it possible to write different implementations for each platform. This is also great for some user interface code, you can use 3rd party react components on the web and 3rd party react native components on mobile that look similar to implement more complex user interactions since react native web supports all regular react code and jsx tags on the web.
I was able to get past this error by adding:
config.module.strictExportPresence = false in the config-override.js
Now i am stuck on further issues.
Original issue in the question is gone by this. I will post with any other related updates if i have any.

Does ReactJS reuse imported packages?

Does ReactJS reuse imported packages?
Let's say I have a file called DisplayItems.js and EditItem.js. They are both imported into App.js.
If I import a package (like axios) at the top of my DisplayItem.js file (import axios from 'axios';), and I also import it in my EditItem.js file, does my Application grow by 13kb or 26kb (assuming axios is 13kb)?
This behavior is controlled not by React, but by whatever build tool compiles and bundles your import statements into a JavaScript file for the browser.
The Create React App template currently uses Webpack as its build tool. Webpack avoids duplicating code that is imported multiple times; it only writes the definitions once. If you are using a different project setup for your React app, your project may use a different build tool.
In response to jhpratt, I did think of testing it on my own, but I knew it would take some time (about 34 mins).
Here's the test results.
Importing jQuery
2742120 (the control) - with jquery imported once
2742353 - with jquery imported twice (233 byte difference, .2kb)
2741887 - with jquery not being imported (233 byte difference, .2kb)
Importing modal-vanilla
2742120 (the control) - with modal-vanilla being imported once
2742406 - with modal-vanilla being import twice (286 byte difference, .3kb)
2712501 - with modal-vanilla not being imported (29386 byte difference, 29.3kb)
I'm not sure what was going on with jQuery (maybe I added it somewhere else in my project?), but it does look like packages are reused (at least in this instance).
Just in case anyone's wondering, I am using Laravel's React setup.

Categories