Skip to content

Commit

Permalink
Wrap: rename route to component for consistency
Browse files Browse the repository at this point in the history
  • Loading branch information
ItalyPaleAle committed Sep 20, 2020
1 parent 8d1bd33 commit c556e72
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 78 deletions.
34 changes: 17 additions & 17 deletions Advanced Usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@ import Router from 'svelte-spa-router'

It accepts a single `options` argument that is an object with the following properties:

- `options.route`: Svelte component to use, statically-included in the bundle. This is a Svelte component, such as `route: Foo`, with that previously imported with `import Foo from './Foo.svelte'`.
- `options.asyncRoute`: Used to dynamically-import route. This must be a function definition that returns a dynamically-imported component, such as: `asyncRoute: () => import('./Foo.svelte')`
- `options.loadingRoute`: Used together with `asyncRoute`, this is a Svelte component, that must be part of the bundle, which is displayed while `asyncRoute` is being downloaded. If this is empty, then the router will not display any component while the request is in progress.
- `options.loadingParams`: When using a `loadingRoute`, this is an optional dictionary that will be passed to the component as the `params` prop.
- `options.component`: Svelte component to use, statically-included in the bundle. This is a Svelte component, such as `component: Foo`, with that previously imported with `import Foo from './Foo.svelte'`.
- `options.asyncComponent`: Used to dynamically-import components. This must be a function definition that returns a dynamically-imported component, such as: `asyncComponent: () => import('./Foo.svelte')`
- `options.loadingComponent`: Used together with `asyncComponent`, this is a Svelte component, that must be part of the bundle, which is displayed while `asyncComponent` is being downloaded. If this is empty, then the router will not display any component while the request is in progress.
- `options.loadingParams`: When using a `loadingComponent`, this is an optional dictionary that will be passed to the component as the `params` prop.
- `options.userData`: Optional dictionary that will be passed to events such as `routeLoading`, `routeLoaded`, `conditionsFailed`.
- `options.conditions`: Array of route pre-condition functions to add, which will be executed in order.

One and only one of `options.route` or `options.asyncRoute` must be set; all other properties are optional.
One and only one of `options.component` or `options.asyncComponent` must be set; all other properties are optional.

You use the `wrap` method in your route definition, such as:

Expand All @@ -54,15 +54,15 @@ import Books from './Books.svelte'
// Using a dictionary to define the route object
const routes = {
'/books': wrap({
route: Books,
component: Books,
userData: {foo: 'bar'}
})
}

// Using a map
const routes = new Map()
routes.set('/books', wrap({
route: Books,
component: Books,
userData: {foo: 'bar'}
}))
```
Expand All @@ -71,19 +71,19 @@ routes.set('/books', wrap({

As mentioned in the main readme, starting with version 3 the `wrap` method is used with dynamically-imported components. This allows (when the bundler supports that, such as with Rollup or Webpack) code-splitting too, so code for less-common routes can be downloaded on-demand from the server rather than shipped in the app's core bundle.

This is done by setting the `options.asyncRoute` property to a function that returns a dynamically-imported module. For example:
This is done by setting the `options.asyncComponent` property to a function that returns a dynamically-imported module. For example:

```js
const routes = {
'/book/:id': wrap({
asyncRoute: () => import('./Book.svelte')
asyncComponent: () => import('./Book.svelte')
})
}
```

Note that the value of `asyncRoute` must be a function definition, such as `() => import(…)`, and **not** `import(…)` (which is a function invocation). The latter would in fact request the module right away (albeit asynchronously), rather than on-demand when needed.
Note that the value of `asyncComponent` must be a function definition, such as `() => import(…)`, and **not** `import(…)` (which is a function invocation). The latter would in fact request the module right away (albeit asynchronously), rather than on-demand when needed.

By default, while a module is being downloaded, the router does not display any component. You can however define a component (which must be statically-included in the app's bundle) to be displayed while the router is downloading a module. This is done with the `options.loadingRoute` property. Additionally, with `options.loadingParams` you can define a JavaScript object/dictionary that is passed to the loading placeholder component as the `params` prop.
By default, while a module is being downloaded, the router does not display any component. You can however define a component (which must be statically-included in the app's bundle) to be displayed while the router is downloading a module. This is done with the `options.loadingComponent` property. Additionally, with `options.loadingParams` you can define a JavaScript object/dictionary that is passed to the loading placeholder component as the `params` prop.

For example, with a `Loading.svelte` component:

Expand Down Expand Up @@ -112,9 +112,9 @@ const routes = {
// Wrapping the Book component
'/book/*': wrap({
// Dynamically import the Book component
asyncRoute: () => import('./Book.svelte'),
asyncComponent: () => import('./Book.svelte'),
// Display the Loading component while the request for the Book component is pending
loadingRoute: Loading,
loadingComponent: Loading,
// Value for `params` in the Loading component
loadingParams: {
message: 'secret',
Expand All @@ -138,12 +138,12 @@ import Books from './Books.svelte'
const routes = {
// Using a statically-included component and adding user data
'/books': wrap({
route: Books,
component: Books,
userData: {foo: 'bar'}
}),
// Same, but for dynamically-loaded components
'/authors': wrap({
asyncRoute: () => import('./Authors.svelte'),
asyncComponent: () => import('./Authors.svelte'),
userData: {hello: 'world'}
})
}
Expand Down Expand Up @@ -183,7 +183,7 @@ const routes = {
// This route has a pre-condition function that lets people in only 50% of times, and a second pre-condition that is always true
'/lucky': wrap({
// The Svelte component used by the route
route: Lucky,
component: Lucky,
// Custom data: any JavaScript object
// This is optional and can be omitted
Expand Down Expand Up @@ -224,7 +224,7 @@ const routes = {
// This route has an async function as pre-condition
'/admin': wrap({
// Use a dynamically-loaded component for this
asyncRoute: () => import('./Admin.svelte'),
asyncComponent: () => import('./Admin.svelte'),
// Adding one pre-condition that's an async function
conditions: [
async (detail) => {
Expand Down
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,26 +127,26 @@ The `routes` prop is the dictionary defined above.

That's it! You already have all that you need for a fully-functional routing experience.

### Dynamically-imported routes and code-splitting
### Dynamically-imported components and code-splitting

Starting with version 3.0, svelte-spa-router supports dynamically-imported routes (via the `import()` method). The advantage of using dynamic imports is that, if your bundler supports that, you can enable code-splitting and reduce the size of the bundle you send to your users. This has been tested with bundlers including Rollup and Webpack.
Starting with version 3.0, svelte-spa-router supports dynamically-imported components (via the `import()` construct). The advantage of using dynamic imports is that, if your bundler supports that, you can enable code-splitting and reduce the size of the bundle you send to your users. This has been tested with bundlers including Rollup and Webpack.

To use dynamically-imported routes, you need to leverage the `wrap` method (the same one that enables support for [route pre-conditions](/Advanced%20Usage.md#route-pre-conditions)). First, import the `wrap` method:
To use dynamically-imported components, you need to leverage the `wrap` method (which can be used for a variety of actions, as per the docs on [route wrapping](/Advanced%20Usage.md#route-wrapping)). First, import the `wrap` method:

```js
import {wrap} from 'svelte-spa-router/wrap'
```

Then, in your route definition, wrap your routes using the `wrap` method, passing a function that returns the dynamically-imported component to the `asyncRoute` property:
Then, in your route definition, wrap your routes using the `wrap` method, passing a function that returns the dynamically-imported component to the `asyncComponent` property:

```js
wrap({
asyncRoute: () => import('./Foo.svelte')
asyncComponent: () => import('./Foo.svelte')
})
```

> Note: the value of `asyncRoute` must be the **definition of a function** returning a dynamically-imported component, such as `asyncRoute: () => import('./Foo.svelte')`.
> Do **not** use `asyncRoute: import('./Foo.svelte')`, which is a function invocation instead.
> Note: the value of `asyncComponent` must be the **definition of a function** returning a dynamically-imported component, such as `asyncComponent: () => import('./Foo.svelte')`.
> Do **not** use `asyncComponent: import('./Foo.svelte')`, which is a function invocation instead.
For example, to make the Author and Book routes from the first example dynamically-imported, we'd update the code to:

Expand All @@ -163,12 +163,12 @@ const routes = {

// Wrapping the Author component
'/author/:first/:last?': wrap({
asyncRoute: () => import('./routes/Author.svelte')
asyncComponent: () => import('./routes/Author.svelte')
}),

// Wrapping the Book component
'/book/*': wrap({
asyncRoute: () => import('./routes/Book.svelte')
asyncComponent: () => import('./routes/Book.svelte')
}),

// Catch-all route last
Expand All @@ -178,7 +178,7 @@ const routes = {

The `wrap` method accepts an object with multiple properties and enables other features, including: setting a "loading" component that is shown while a dynamically-imported component is being requested, adding custom user data, adding pre-conditions (route guards), etc.

You can learn more about all the features of `wrap` in the documentation for [Route wrapping](/Advanced%20Usage.md#route-wrapping).
You can learn more about all the features of `wrap` in the documentation for [route wrapping](/Advanced%20Usage.md#route-wrapping).

### Navigating between pages

Expand Down
16 changes: 8 additions & 8 deletions Router.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,20 @@ import {tick} from 'svelte'
import {wrap as _wrap} from './wrap'
/**
* Wraps a route to add route pre-conditions.
* Wraps a component to add route pre-conditions.
* @deprecated Use `wrap` from `svelte-spa-router/wrap` instead. This function will be removed in a later version.
*
* @param {SvelteComponent} route - Svelte component for the route
* @param {SvelteComponent} component - Svelte component for the route
* @param {Object} [userData] - Optional object that will be passed to each `conditionsFailed` event
* @param {...function(RouteDetail): boolean} conditions - Route pre-conditions to add, which will be executed in order
* @returns {WrappedRoute} Wrapped route
* @returns {WrappedComponent} Wrapped component
*/
export function wrap(route, userData, ...conditions) {
export function wrap(component, userData, ...conditions) {
// Use the new wrap method and show a deprecation warning
// eslint-disable-next-line no-console
console.warn('Method `wrap` from `svelte-spa-router` is deprecated and will be removed in a future version. Please use `svelte-spa-router/wrap` instead. See http://bit.ly/svelte-spa-router-upgrading')
return _wrap({
route,
component,
userData,
conditions
})
Expand Down Expand Up @@ -247,7 +247,7 @@ export let prefix = ''
export let restoreScrollState = false
/**
* Optional props that are passed to each route in the component, expanded (with `{...props}`)
* Optional props that are passed to each component in the router, expanded (with `{...props}`)
*/
export let props = {}
Expand Down Expand Up @@ -280,7 +280,7 @@ class RouteItem {
// Check if the component is wrapped and we have conditions
if (typeof component == 'object' && component._sveltesparouter === true) {
this.component = component.route
this.component = component.component
this.conditions = component.conditions || []
this.userData = component.userData
}
Expand Down Expand Up @@ -345,7 +345,7 @@ class RouteItem {
/**
* Dictionary with route details passed to the pre-conditions functions, as well as the `routeLoading`, `routeLoaded` and `conditionsFailed` events
* @typedef {Object} RouteDetail
* @property {string|Object} route - Route matched as defined in the route definition (could be a string or a reguar expression object)
* @property {string|RegExp} route - Route matched as defined in the route definition (could be a string or a reguar expression object)
* @property {string} location - Location path
* @property {string} querystring - Querystring from the hash
* @property {Object} [userData] - Custom data passed by the user
Expand Down
6 changes: 3 additions & 3 deletions UPGRADING.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ If your application was decoding URL parameters before, remove that invocation w

### New `wrap` method

The `wrap` method exported by `svelte-spa-router` has been deprecated. Even though it remains available and functional (albeit showing a warning), it will be removed in a later version of the router.
The `wrap` method exported by `svelte-spa-router` has been deprecated. Even though it remains available and functional (albeit showing a warning in the console), it will be removed in a later version of the router.

Please use the new `wrap` method exported by `svelte-spa-router/wrap` instead. This method's signature accepts a single argument which is an object of properties. It adds support for many other features too, such as dynamically-imported routes.

Expand All @@ -34,7 +34,7 @@ To upgrade, maintaining the same functionality:
import {wrap} from 'svelte-spa-router'

const routes = {
// Method signature: wrap(route, userData, ...conditions)
// Method signature: wrap(component, userData, ...conditions)
'/foo': wrap(
// Component
Foo,
Expand All @@ -59,7 +59,7 @@ const routes = {
// Method signature: wrap(options)
'/foo': wrap({
// Component
route: Foo,
component: Foo,
// Custom data
customData: {foo: 'bar'},
// Pre-condition function
Expand Down
18 changes: 9 additions & 9 deletions examples/dynamic-imports/src/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ export default {
// This is dynamically imported, so the code is loaded on-demand from the server
'/hello/:first/:last?': wrap({
// Note that this is a function that returns the import
asyncRoute: () => import('./routes/Name.svelte'),
// Show the loading component while the route is being downloaded
loadingRoute: Loading,
// Pass values for the `params` prop of the loading route
asyncComponent: () => import('./routes/Name.svelte'),
// Show the loading component while the component is being downloaded
loadingComponent: Loading,
// Pass values for the `params` prop of the loading component
loadingParams: {
message: 'Loading the Name route…'
}
Expand All @@ -34,17 +34,17 @@ export default {
// Note that this is a function that returns the import
// We're adding an artificial delay of 5 seconds so you can experience the loading even on localhost
// Note that normally the modules loaded with `import()` are cached, so the delay exists only on the first request.
// In this case, we're adding a delay every time the route is loaded
asyncRoute: () => import('./routes/Wild.svelte')
// In this case, we're adding a delay every time the component is loaded
asyncComponent: () => import('./routes/Wild.svelte')
.then((component) => {
return new Promise((resolve) => {
// Wait 5 seconds before returning
setTimeout(() => resolve(component), 5000)
})
}),
// Show the loading component while the route is being downloaded
loadingRoute: Loading,
// Pass values for the `params` prop of the loading route
// Show the loading component while the component is being downloaded
loadingComponent: Loading,
// Pass values for the `params` prop of the loading component
loadingParams: {
message: 'Loading the Wild route…'
}
Expand Down
16 changes: 8 additions & 8 deletions test/app/src/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@ import Regex from './routes/Regex.svelte'
import NotFound from './routes/NotFound.svelte'

const wrappedLuckyRoute = wrap({
// Add an artificial delay so we can experience the route loading
asyncRoute: () => import('./routes/Lucky.svelte')
// Add an artificial delay so we can experience the component loading
asyncComponent: () => import('./routes/Lucky.svelte')
.then((res) => {
return new Promise((resolve) => {
setTimeout(() => resolve(res), 2000)
})
}),
// Component to show while the module is being downloaded
loadingRoute: Loading,
loadingComponent: Loading,
// Props for the loading component
loadingParams: {message: 'secret'},
// Set some user data
Expand Down Expand Up @@ -87,7 +87,7 @@ if (!urlParams.has('routemap')) {
'/wild': Wild,
// Special route that has custom data that will be passed to the `routeLoaded` event
'/wild/data': wrap({
route: Wild,
component: Wild,
userData: {hello: 'world'}
}),
'/wild/*': Wild,
Expand All @@ -99,10 +99,10 @@ if (!urlParams.has('routemap')) {
// This component contains a nested router
// Note that we must match both '/nested' and '/nested/*' for the nested router to work (or look below at doing this with a Map and a regular expression)
'/nested': wrap({
asyncRoute: () => import('./routes/Nested.svelte')
asyncComponent: () => import('./routes/Nested.svelte')
}),
'/nested/*': wrap({
asyncRoute: () => import('./routes/Nested.svelte')
asyncComponent: () => import('./routes/Nested.svelte')
}),

// Catch-all, must be last
Expand All @@ -125,7 +125,7 @@ else {
routes.set('/wild', Wild)
// Special route that has custom data that will be passed to the `routeLoaded` event
routes.set('/wild/data', wrap({
route: Wild,
component: Wild,
userData: {hello: 'world'}
}))
routes.set('/wild/*', Wild)
Expand All @@ -141,7 +141,7 @@ else {
// This component contains a nested router
// Thanks to being able to define routes via regular expressions, this allows us to use a single line rather than 2 ('/nested' and '/nested/*')
routes.set(/^\/nested(\/(.*))?/, wrap({
asyncRoute: () => import('./routes/Nested.svelte')
asyncComponent: () => import('./routes/Nested.svelte')
}))

// Catch-all, must be last
Expand Down
Loading

0 comments on commit c556e72

Please sign in to comment.