
Research
Security News
Lazarus Strikes npm Again with New Wave of Malicious Packages
The Socket Research Team has discovered six new malicious npm packages linked to North Korea’s Lazarus Group, designed to steal credentials and deploy backdoors.
@dark-engine/web-router
Advanced tools
The isomorphic Dark router designed for rendering universal web applications that work both on the client and on the server
The isomorphic Dark router designed for rendering universal web applications that work both on the client and on the server.
npm:
npm install @dark-engine/web-router
yarn:
yarn add @dark-engine/web-router
CDN:
<script src="https://unpkg.com/@dark-engine/web-router/dist/umd/dark-web-router.production.min.js"></script>
import {
type Routes,
type RouterRef,
Router,
Link,
NavLink,
useLocation,
useHistory,
useParams,
useMatch,
usePending,
VERSION,
} from '@dark-engine/web-router';
const routes: Routes = [
{ path: 'first-component', component: FirstComponent },
{ path: 'second-component', component: SecondComponent },
];
const App = component(() => {
return (
<Router routes={routes}>
{slot => {
return (
<>
<header>
<NavLink to='/first-component'>first-component</NavLink>
<NavLink to='/second-component'>second-component</NavLink>
</header>
<main>{slot}</main> {/*<-- a route content will be placed here*/}
</>
);
}}
</Router>
);
});
<base href>
You must add the element to the application's index.html for pushState routing to work.
<base href="/">
Also you must pass the baseUrl to Router if it is different from /
.
<Router routes={routes} baseUrl={YOUR_BASE_URL}>{slot => slot}</Router>
The order of routes is important because the Router uses a first-match wins strategy when matching routes, so more specific routes should be placed above less specific routes. List routes with a static path first, followed by an empty path route, which matches the default route. The wildcard route comes last because it matches every URL and the Router selects it only if no other routes match first.
const FirstComponent = component(() => {
const location = useLocation(); // url, protocol, host, pathname, search, key
const match = useMatch(); // url prefix for links
return <div>FirstComponent</div>;
});
{ path: '**', component: ComponentName }
const routes: Routes = [
{ path: 'first-component', component: FirstComponent },
{ path: 'second-component', component: SecondComponent },
{ path: '**', component: PageNotFoundComponent }, // Wildcard route for a 404 page
];
const routes: Routes = [
{ path: 'first-component', component: FirstComponent },
{ path: 'second-component', component: SecondComponent },
{ path: '', redirectTo: '/first-component', pathMatch: 'full' }, // redirect to `first-component`
{ path: '**', component: PageNotFoundComponent }, // Wildcard route for a 404 page
];
const routes: Routes = [
{
path: 'first-component',
component: FirstComponent, // The component receives children routes as slot
children: [
{
path: 'child-a',
component: ChildAComponent,
},
{
path: 'child-b',
component: ChildBComponent,
},
],
},
];
const routes: Routes = [
{
path: 'first-component/child-a',
component: ChildAComponent,
},
{
path: 'first-component/child-b',
component: ChildBComponent,
},
{
path: 'first-component',
component: FirstComponent, // In this case slot will be null
},
];
const routes: Routes = [
{
path: 'first-component',
component: FirstComponent,
children: [
{
path: 'child-a',
component: ChildAComponent,
},
{
path: 'child-b',
component: ChildBComponent,
},
{
path: '**',
redirectTo: 'child-a',
},
],
},
];
or
const routes: Routes = [
{
path: 'first-component',
component: FirstComponent,
children: [
{
path: 'child-a',
component: ChildAComponent,
},
{
path: 'child-b',
component: ChildBComponent,
},
{
path: '**',
component: PageNotFoundComponent,
},
],
},
];
Link
or NavLink
<Link to='/user/50'>Go to profile</Link>
<NavLink to='/home'>Home</NavLink>
NavLink
internally uses Link
, but at the same time provides a CSS class .active-link
if the current URL is equal to or contains the to
parameter of NavLink
.
NavLink
can be used for headers and menus, which will continue to be on the page when it is clicked and the content is changed.
Link
means that it will disappear from the screen after you click it and go to another page. Of course you can create your own logic based on Link
, using it as a base component.
history
const SomeComponent = component(() => {
const history = useHistory();
useEffect(() => {
history.push('/home'); // or history.replace('/home');
}, []);
return <div>SomeComponent</div>;
});
Sometimes, a feature of your application requires accessing a part of a route, such as a parameter like id of something. You can define parameterized route like below.
const routes: Routes = [
{
path: 'first-component/:id',
component: FirstComponent,
},
{
path: 'second-component',
component: SecondComponent,
},
];
Then get access for parameter through hook
const FirstComponent = component(() => {
const params = useParams();
const id = Number(params.get('id'));
return <div>FirstComponent: {id}</div>;
});
You can configure your routes to lazy load modules, which means that Dark only loads modules as needed, rather than loading all modules when the application launches.
import { lazy } from '@dark-engine/core';
const Home = lazy(() => import('../components/home'));
const About = lazy(() => import('../components/about'));
const Contacts = lazy(() => import('../components/contacts'));
const routes: Routes = [
{
path: 'home',
component: Home,
},
{
path: 'about',
component: About,
},
{
path: 'contacts',
component: Contacts,
},
];
const App = component<AppProps>(({ url, routes }) => {
const ref = useRef<RouterRef>(null);
useEffect(() => {
ref.current.navigateTo('/about');
}, []);
return (
<Router ref={ref} routes={routes}>
{slot => slot}
</Router>
);
});
If you are rendering the application on the server, then you must pass the request URL to the router to emulate routing when rendering to a string.
server.get('*', async (req, res) => {
const { url } = req;
const app = await renderToString(Page({ title: 'My App', slot: App({ url }) }));
const page = `<!DOCTYPE html>${app}`;
res.statusCode = 200;
res.send(page);
});
const App = component(({ url }) => {
<Router routes={routes} url={url}>{slot => slot}</Router>
})
Full example SSR routing you can see in /examples
.
In this mode, the router will automatically render through non-blocking transitions, using startTransition
under the hood. To track the isPending
flag and show the waiting UI you can use the special usePending
hook.
<Router routes={routes} mode='concurrent'>
{slot => slot}
</Router>
const Pending = component(() => {
const isPending = usePending();
// Makes the content on the screen a little transparent while the transition is in progress.
return <Overlay isPending={isPending} />;
});
MIT © Alex Plex
FAQs
The isomorphic Dark router designed for rendering universal web applications that work both on the client and on the server
The npm package @dark-engine/web-router receives a total of 7 weekly downloads. As such, @dark-engine/web-router popularity was classified as not popular.
We found that @dark-engine/web-router demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
The Socket Research Team has discovered six new malicious npm packages linked to North Korea’s Lazarus Group, designed to steal credentials and deploy backdoors.
Security News
Socket CEO Feross Aboukhadijeh discusses the open web, open source security, and how Socket tackles software supply chain attacks on The Pair Program podcast.
Security News
Opengrep continues building momentum with the alpha release of its Playground tool, demonstrating the project's rapid evolution just two months after its initial launch.