I distributed the bundle using lazy load, the size of the reactApp.bundle decreased significantly, and indeed improved the loading of the application.
In the bundles folder, I have created bundle files whose name expresses the routing to the component that the bundle file records for the sample:
The file: src_pages_employees_index_js.bundle.js
Records the contents of the file:
src>pages>employees>index_js
The src, this is the folder where the reactApp.js file is located and it is documented as a starting point in module.exports in the -webpack.config.js file
so:
module.exports = { entry: { reactApp: path.resolve(__dirname, "./src/reactApp.js"), },
Inside the bundles folder, I have additional files that start with vendors, for example:
vendors-node_modules_material-table_exporters_index_js-node_modules_material-ui_core_esm_Box_-54c6ff.bundle
The bundle files that start with vendors also continue and gain weight as development progresses, I'm trying to understand what their source is in order to handle their splitting, we don't have a folder called vendors in the project, the only mention I found is a json file located inside the node_modules in the following path:
node_modules>ci-info>vendors.json
There doesn't seem to be a connection, but it makes sense, I couldn't understand the connection, and how do I locate the reasons for recording the content in these files in order to handle their splitting,
I am trying to find what are the files documented in the bundle files starting with vendors
The files that start with the 'vendor' are bundle files that are created as a result of importing external packages, such as material and the like,
To improve the loading time for these components, you can use the lazy loader
for example:
import React, { lazy, Suspense } from "react";
import { makeStyles } from "#material-ui/core/styles";
const Tabs = lazy(() => import("#material-ui/core/Tabs"));
const Tab = lazy(() => import("#material-ui/core/Tab"));
const Box = lazy(() => import("#material-ui/core/Box"));
When using components imported via lazy they must be wrapped in suspense
for example:
function App() {
const classes = makeStyles({
root: {
flexGrow: 1,
backgroundColor: "#fff",
},
})();
return (
<div className={classes.root}>
<Suspense fallback={<div>Loading Material-UI components...</div>}>
<Tabs value={0} aria-label="simple tabs example">
<Tab label="Item One" />
<Tab label="Item Two" />
<Tab label="Item Three" />
</Tabs>
<Box>Some content here</Box>
</Suspense>
</div>
);
}
export default App;
Related
I have an app with some stories already, and I just installed Ladle alongside Storybook. I plan on running both Ladle and Storybook – Ladle for quick iteration in developing the UI and Storybook for interaction testing and other addons.
Running npx ladle serve opens up the browser, and all the stories are detected. However, the display window (main.ladle-main) is completely blank.
On the same branch, Storybook itself runs just fine. I ran the ladle server with debug, but I don't really know what to make of any of its output.
Most of my stories have play functions, I don't know if that's the issue.
I also copied my global decorator from my storybook preview file to .ladle/components.tsx
import type { GlobalProvider } from "#ladle/react";
import { AppWrapper } from "../src/AppWrapper";
export const Provider: GlobalProvider = ({ children, globalState }) => (
<>
<header>
<link
href="https://fonts.googleapis.com/css?family=Roboto:100,200,300,400,500,600,700"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css?family=Roboto+Condensed:400,500,600,700"
rel="stylesheet"
/>
</header>
<AppWrapper>{children}</AppWrapper>
</>
);
I'm not able to access the images folder. components available in src directly are able to access the images folder but components in the pages folder are not able to access the images folder, tried different paths but not working.
import React from "react";
import TitleImg from "../images/title-text.png";
import eyes from "../images/eyes.png";
const Sad = () => {
return (
<>
<img src={TitleImg} alt="the-sad-guys" />
<img className="w-3/6" src={eyes} alt="eyes" />
</>
);
};
export default Sad;
In your example the route is not correct. ../../images/title-text.png must work.
If this doesnt work, try
./../../images/title-text.png
I have some Svg files which i want to load as react components in remix run app.
for example in create-react-app your could do something like this
import { ReactComponent as Logo } from './logo.svg';
function App() {
return (
<div>
{/* Logo is an actual React component */}
<Logo />
</div>
);
}
is there any similar way in remix-run do achieve the same ?
I created a workflow to convert the icons to react components in development using svgr and npm-watch. For good measure you will probably want to run the icons script before building for production too.
Install dependencies:
npm install -D #svgr/cli #svgr/plugin-svgo #svgr/plugin-jsx #svgr/plugin-prettier npm-watch npm-run-all
Update package.json scripts:
{
//...
"scripts": {
//...
// task to convert icons to components
"icons": "npx #svgr/cli --out-dir app/icons -- ./icons",
// watch task
"icons:watch": "npm-watch icons",
// compile once and start watching for changes
"dev:svg": "run-s icons icons:watch",
// remix dev
"dev:remix": "remix dev",
// run all dev: scripts including `dev:svg` (depending on the remix template you might need to replace the default `dev` script)
"dev": "run-p dev:*"
},
// npm-watch configuration
"watch": {
"icons": {
"patterns": [
"icons"
],
"extensions": "svg",
"quiet": false
}
},
//...
}
The svg icon files are located in the project root in icons/ and the react components are generated in the app/icons/ folder.
svgr.config.js (optional)
module.exports = {
plugins: ["#svgr/plugin-svgo", "#svgr/plugin-jsx", "#svgr/plugin-prettier"],
typescript: true, // optional
};
svgo.config.js
module.exports = {
plugins: [
{
name: "preset-default",
params: {
overrides: {
removeViewBox: false,
},
},
},
],
};
Unfortunately there is no way currently to import an SVG file in your component file directly like in create react app.
And maintainers do not allow currently manipulating the esbuild config to add features like that via plugins (cf. the discussion in this merge request).
If you don't need to style your SVG, you could simply put it in the public/ folder and include it with an img element in your component.
Smaller JS bundles, faster page hydration, and immutable .svg's over the network that are only ever downloaded once. (cf. this message)
function App() {
return (
<div>
<img src="/logo.svg" alt="My logo" />
</div>
);
}
You could also create yourself a JSX component and put your SVG code inside it (with some manual conversion for prop names), or even put your SVG file in a folder, and use an external automatic conversion tool like SVGR to generate optimized JSX component from it with a simple CLI command.
In that case you have a component that you can import like any other component:
import Logo from './Logo.svg';
function App() {
return (
<div>
<Logo />
</div>
);
}
For me, it only worked by creating a component with the SVG tag and then importing it
const HomeLogo = () => {
return (
<div>
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48">
<g fill="none" fill-rule="evenodd">
<circle cx="24" cy="24" r="24" fill="#FFF"/>
<path fill="#0B0D17" d="M24 0c0 16-8 24-24 24 15.718.114 23.718 8.114 24 24 0-16 8-24 24-24-16 0-24-8-24-24z"/>
</g>
</svg>
</div>
)
}
export default HomeLogo
You can just import them as described in the documentation:
import type { LinksFunction } from "#remix-run/node"; // or "#remix-run/cloudflare"
import styles from "./styles/app.css";
import banner from "./images/banner.jpg";
export const links: LinksFunction = () => {
return [{ rel: "stylesheet", href: styles }];
};
export default function Page() {
return (
<div>
<h1>Some Page</h1>
<img src={banner} />
</div>
);
}
I have a website serving photos in a gallery format that I've created using Next.js. I have all my images stored in /public/photos/ grouped into subfolders, and they are imported where they are needed (see below).
The main page consists of a grid (the tiles component) of individual tiles (the tile component) with a photo background and a title. The photo is imported into tiles.tsx and passed to the tile component as a prop, so I can add more tiles easily.
When I compile this project with npm run dev, I get this error:
error - ./public/photos/astro/astro.png
Module parse failed: Unexpected character '�' (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file.
My webpack config is as follows:
const webpack = require('webpack');
const path = require('path');
module.exports = {
module: {
rules: [
{
test: /\.(png|jpe?g|gif)$/i,
use: [
{
loader: 'file-loader',
},
],
},
],
}
};
tiles.tsx is as follows:
import React from "react";
import Tile from "./tile";
import styles from "#styles/tiles.module.css";
import landscape from "../public/photos/landscape/landscape.png";
import astro from "../public/photos/astro/astro.png";
import cgi from "../public/photos/cg/cg.png";
import flowers from "../public/photos/flowers/flowers.png";
function Tiles() {
return(
<div>
<div className={styles.gallery}>
<Tile title="Landscape" photo={landscape} location="landscape"/>
<Tile title="Astro" photo={astro} location="astro"/>
<Tile title='CGI' photo={cgi} location="cgi"/>
<Tile title="Flowers" photo={flowers} location="flowers"/>
</div>
</div>
);
}
export default Tiles;
tile.tsx is as follows:
import styles from '#styles/tile.module.css'
const Tile = (props) => {
return(
<div>
<a className={styles.linkWrapper} href={props.location}>
<div className={styles.imageContainer}>
<img className={styles.image} src={props.photo}/>
<div className={styles.title}>{props.title}</div>
</div>
</a>
</div>
);
}
export default Tile;
I believe I have my webpack correctly configured to load these files. This error only occurs with png images, jpegs and jpgs pose no issue. I have tried to resolve this with next-images, but was unsuccessful.
Any help if appreciated. I am happy to provide extra code if necessary.
Since your pictures are located in the public folder, and to avoid having the extra configuration to load image files, you can simply reference each image by their path in the public folder starting from the base URL (/).
function Tiles() {
return(
<div>
<div className={styles.gallery}>
<Tile title="Landscape" photo="/photos/landscape/landscape.png" location="landscape"/>
<Tile title="Astro" photo="/photos/astro/astro.png" location="astro"/>
<Tile title='CGI' photo="/photos/cg/cg.png" location="cgi"/>
<Tile title="Flowers" photo="/photos/flowers/flowers.png" location="flowers"/>
</div>
</div>
);
}
Check out Static File Serving for more details.
I am new to gatsbyjs and using v2.
I've 3 components - loader, header and layout.
layout.js
import React from "react"
import Helmet from 'react-helmet'
import { StaticQuery, graphql } from 'gatsby'
import Header from "./header"
import Loader from "./loader"
import 'bootstrap/dist/css/bootstrap.min.css'
import "./layout.module.css"
const Layout = ({ children }) => (
<StaticQuery
query={graphql`
query SiteTitleQuery {
site {
siteMetadata {
title
menuLinks {
name
link
}
}
}
}
`}
render={data => (
<React.Fragment>
<Helmet
title={'tite'}
meta={[
{ name: 'description', content: 'Sample' },
{ name: 'keywords', content: 'sample, something' },
]}
>
</Helmet>
<Loader />
<Header menuLinks={data.site.siteMetadata.menuLinks} siteTitle={data.site.siteMetadata.title} />
<div>{children}</div>
</React.Fragment>
)}
/>
)
export default Layout
In index.js
import React from 'react'
import Layout from "../components/layout"
export default () => (
<Layout>
</Layout>
)
Every component is being rendered twice as shown in screenshot.
Another issue I am facing with images. All the images are in src/images/ and when I use it as below in header component:
import React from "react"
import { Link } from 'gatsby'
import styles from "./layout.module.css"
const logo = 'src/images/logo.png';
const Header = ({ siteTitle, menuLinks }) => (
<header className={styles.header_area}>
<nav className={`${styles.navbar} navbar-expand-lg ${styles.menu_one} ${styles.menu_four}`}>
<div className="container">
<a className="navbar-brand sticky_logo" href="#">
<img src={logo} alt="logo" />
The image doesn't show up on a page. I checked Source in chrome developer tools and found that images are not being served via webpack.
So, why components render twice and why image doesn't show up ? what am I missing or doing worng here ?
I had the same issue when using the gatsby-plugin-layout plugin. The doc is not really clear, but when using the gatsby-plugin-layout plugin, you don't need to wrap your page between the Layout component. That plugin takes care of this automatically. If you explicitly wrap your JSX between the Layout component, the Layout is rendered twice.
I'm not sure why your page is loading double components, are you coming to the site directly, or from another path?
For your image not showing up, this is why:
Everything in your src folder is meant to be dynamic, meaning it won't be served directly. If you want to include image statically, you can create a public folder in your root directory (at the same level with src folder), and put images in there. Anything in this public folder will be served directly. So for example, you can have this structure:
|-- src
`-- public
`-- images
`-- logo.png
Then in your code, you can include the path like
<img src="/images/logo.png" alt="logo" />
I think for a logo like your use case, this method is sufficient. However, if you always link images like this, you'll be missing out a lot of gatsby's cool feature. For example, gatsby can load your image lazily, or optimize the file size! You can learn more here (gatsby official blog).