kyt-starter-universal
Advanced tools
Comparing version
{ | ||
"name": "kyt-starter-universal", | ||
"version": "2.0.3-next1.10+d9fd22c", | ||
"version": "2.0.3-next1.11+ae2522c", | ||
"description": "", | ||
@@ -15,3 +15,3 @@ "repository": { | ||
"homepage": "https://github.com/nytimes/kyt/packages/kyt-starter-universal#readme", | ||
"gitHead": "d9fd22cf07143a7aedbad05f1799eeee44a92db9" | ||
"gitHead": "ae2522c99d66b347bb52b426a6776f521af21f05" | ||
} |
@@ -10,3 +10,5 @@ module.exports = { | ||
], | ||
plugins: [], | ||
plugins: [ | ||
'kyt-runtime/babel' | ||
], | ||
env: { | ||
@@ -13,0 +15,0 @@ production: { |
@@ -31,3 +31,3 @@ { | ||
"express": "4.17.1", | ||
"kyt-runtime": "1.2.50-next1.8+d6cf3a2", | ||
"kyt-runtime": "1.2.50-next1.10+d9fd22c", | ||
"pretty-lights": "0.0.20", | ||
@@ -48,6 +48,6 @@ "prop-types": "15.7.2", | ||
"sass-embedded": "^1.69.5", | ||
"babel-preset-kyt-react": "1.3.21-next1.13+02b9c08", | ||
"babel-preset-kyt-react": "1.3.21-next1.16+d9fd22c", | ||
"eslint": "7.32.0", | ||
"eslint-config-airbnb": "18.2.1", | ||
"eslint-config-kyt": "1.6.4-next1.13+d6cf3a2", | ||
"eslint-config-kyt": "1.6.4-next1.16+d9fd22c", | ||
"eslint-config-prettier": "8.3.0", | ||
@@ -66,4 +66,3 @@ "eslint-plugin-import": "2.24.2", | ||
"jest-preset-kyt-styled": "1.4.12", | ||
"kyt": "1.2.10-next1.6+d6cf3a2", | ||
"@loadable/babel-plugin": "^5.15.3", | ||
"kyt": "1.2.10-next1.8+d9fd22c", | ||
"prettier": "2.8.8" | ||
@@ -70,0 +69,0 @@ }, |
@@ -6,4 +6,5 @@ import React from 'react'; | ||
// Wait for dynamic imports to be ready before hydrating | ||
preloadDynamicImports().then(() => { | ||
hydrate(<Root />, document.querySelector('#root')); | ||
}); |
@@ -1,5 +0,4 @@ | ||
import React, { useEffect } from 'react'; | ||
import React from 'react'; | ||
import { Switch, Route, Link, useLocation } from 'react-router-dom'; | ||
import dynamic from 'kyt-runtime/dynamic'; | ||
import loadable from '@loadable/component'; | ||
import styles from './styles.module.scss'; | ||
@@ -9,12 +8,7 @@ import { logoClass } from './styled'; | ||
// Dynamic imports for code splitting | ||
export const Home = dynamic(() => import(/* webpackChunkName: "home" */ '../Home'), { | ||
ssr: true // Enable server-side rendering | ||
}); | ||
const Home = loadable(() => import(/* webpackChunkName: "home" */ '../Home')); | ||
export const Tools = dynamic(() => import(/* webpackChunkName: "tools" */ '../Tools'), { | ||
ssr: true // Enable server-side rendering | ||
}); | ||
const Tools = loadable(() => import(/* webpackChunkName: "tools" */ '../Tools')); | ||
export default function App() { | ||
const location = useLocation(); | ||
@@ -21,0 +15,0 @@ return ( |
@@ -18,3 +18,12 @@ // Handle uncaught errors | ||
import { StaticRouter } from 'react-router-dom'; | ||
import { preloadDynamicImports, DynamicImports, getBundles, loadAssets } from 'kyt-runtime/server'; | ||
// Import utilities from kyt-runtime/server | ||
import { | ||
loadAssets, | ||
getBundles | ||
} from 'kyt-runtime/server'; | ||
// Import ChunkExtractor and ChunkExtractorManager directly from @loadable/server | ||
import { ChunkExtractor, ChunkExtractorManager } from '@loadable/server'; | ||
import { extractCritical } from 'pretty-lights/server'; | ||
@@ -26,3 +35,2 @@ const { publicDir } = require('kyt-utils/paths')(); | ||
import App from '../components/App'; | ||
const isDev = process.env.NODE_ENV === 'development'; | ||
@@ -39,33 +47,43 @@ // Remove annoying Express header addition. | ||
// Setup server side routing. | ||
app.get('*', (req, res) => { | ||
app.get('*', async (req, res) => { | ||
const context = {}; | ||
// Load assets and loadable stats | ||
const { assets, statsFile } = loadAssets({ isDev }); | ||
const { assets, stats } = loadAssets(); | ||
// Track modules for code splitting | ||
const modules = []; | ||
// Force preload of dynamic components based on the route | ||
// This ensures they're included in the modules array | ||
if (req.url === '/') { | ||
modules.push('home'); | ||
} else if (req.url === '/tools') { | ||
modules.push('tools'); | ||
// Only create a ChunkExtractor if we have valid stats (not in dev mode) | ||
let extractor = null; | ||
if (stats) { | ||
try { | ||
extractor = new ChunkExtractor({ | ||
stats, | ||
entrypoints: ['main'], | ||
namespace: 'loadable' | ||
}); | ||
} catch (e) { | ||
console.error('Error initializing ChunkExtractor:', e); | ||
} | ||
} | ||
// Render the app and collect modules | ||
const { html, ids, css } = extractCritical( | ||
renderToString( | ||
<DynamicImports report={moduleName => { | ||
console.log(`Reporting module: ${moduleName}`); | ||
modules.push(moduleName); | ||
}}> | ||
// Wrap the app with ChunkExtractorManager to collect chunks during rendering | ||
const appElement = extractor | ||
? ( | ||
<ChunkExtractorManager extractor={extractor}> | ||
<StaticRouter location={req.url} context={context}> | ||
<App /> | ||
</StaticRouter> | ||
</ChunkExtractorManager> | ||
) | ||
: ( | ||
<StaticRouter location={req.url} context={context}> | ||
<App /> | ||
</StaticRouter> | ||
</DynamicImports> | ||
) | ||
); | ||
// Render the app and collect critical CSS | ||
const { html, ids, css } = extractCritical( | ||
renderToString(appElement) | ||
); | ||
// Handle redirects and status codes | ||
if (context.status && context.status.code) { | ||
@@ -77,14 +95,14 @@ let message = context.status.message || 'Error!'; | ||
res.status(context.status.code).send(message); | ||
return; | ||
} else if (context.redirect && context.redirect.url) { | ||
res.redirect(context.redirect.code || 302, context.redirect.url); | ||
return; | ||
} | ||
// Get all necessary bundles | ||
const bundles = getBundles({ modules, assets, statsFile }); | ||
// Get bundles for the page using the extractor | ||
const bundles = getBundles({ | ||
extractor, | ||
assets, | ||
}); | ||
// If we have a cssModulesStyles path but it's not in the styles array, add it | ||
if (bundles.cssModulesStyles && !bundles.styles.includes(bundles.cssModulesStyles)) { | ||
bundles.styles.push(bundles.cssModulesStyles); | ||
} | ||
res.status(200).send( | ||
@@ -95,3 +113,3 @@ template({ | ||
css, | ||
bundles | ||
bundles, | ||
}) | ||
@@ -101,9 +119,8 @@ ); | ||
preloadDynamicImports().then(() => { | ||
app.listen(port, (err) => { | ||
if (err) { | ||
console.error(err); | ||
} | ||
console.info(`✅ server started on port: ${port}`); | ||
}); | ||
// Start the server | ||
app.listen(port, (err) => { | ||
if (err) { | ||
console.error(err); | ||
} | ||
console.info(`✅ server started on port: ${port}`); | ||
}); |
import favicon from '../public/kyt-favicon.png'; | ||
const getDeferScript = src => `<script defer src="${src}"></script>`; | ||
const getStylesheet = href => `<link rel="stylesheet" type="text/css" href="${href}" />`; | ||
@@ -22,3 +23,3 @@ export default ({ html, ids, css, bundles = {} }) => { | ||
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css" /> | ||
${styles.map(style => `<link rel="stylesheet" type="text/css" href="${style}" />`).join('\n')} | ||
${styles.map(style => getStylesheet(style)).join('\n')} | ||
${css ? `<style data-emotion="${ids.join(' ')}">${css}</style>` : ''} | ||
@@ -25,0 +26,0 @@ </head> |
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
71128
0.15%386
3.76%1
-50%