27 | Proident consectetur deserunt officia consectetur ad aliqua do excepteur
28 | sit.
29 |
30 |
31 | Excepteur reprehenderit minim officia anim occaecat nostrud nulla elit.
32 | Excepteur officia fugiat nisi anim enim quis proident consectetur
33 | exercitation. Consequat eu ea enim ullamco. Amet elit ad sit ipsum magna
34 | consequat exercitation consectetur ullamco.
35 |
180 | <% } %>
181 | <% if(env==='development' ) { %>
182 |
344 | <% } %>
345 |
346 |
347 |
348 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## First start
2 |
3 | In this repository I will discuss about
4 |
5 | - How to define the basic router information in this project ?
6 | - How to use lazy loading in vue-router and customize it ?
7 | - How to use Suspense to create loading page for loading process ?
8 | - How to validate a route ?
9 | - How to protect a route ?
10 |
11 | For more information about this project.
12 |
13 | 1. You can read detail about advanced structure of Webpack + Vue + TS project in this [repository](https://github.com/anhchangvt1994/webpack-project--template-vue-ts).
14 | 2. You can read about vue-router in [here](https://router.vuejs.org/).
15 |
16 | ## Table of contents
17 |
18 | 1. [Install](#install)
19 | 2. [Introduction](#introduction)
20 |
21 |
50 |
51 | ### Table of benefit information that you must know
52 |
53 | - [Define router information](#define)
54 | - [lazy-loading](#lazy-loading)
55 | - [Suspense](#Suspense)
56 | - [Validate on route](#validate)
57 | - [Protect on route](#protect)
58 |
59 |
Define router information
60 | In this project, you can define router information in two ways
61 |
62 | 1. Immediacy
63 |
64 | This way will fast and easy to define and create a vue-router. See code below.
65 |
66 | ```javascript
67 | import HomePage from 'pages/HomePage.vue'
68 |
69 | const routes = [
70 | {
71 | name: 'HomePage',
72 | path: '/',
73 | component: HomePage,
74 | },
75 | ...
76 | ]
77 |
78 | const router = createRouter({
79 | history: createWebHistory('/'),
80 | routes,
81 | sensitive: true,
82 | })
83 | ```
84 |
85 | 2. Define and use it by using environment variables
86 |
87 | This way will make you spend more time to define and create vue-router. But other way you can reuse it to compare route's name, makesure right result when create route's path by using `` and more. See code below
88 |
89 | ```javascript
90 | // env.router.mjs
91 | export default {
92 | prefix: 'router',
93 | data: {
94 | base: {
95 | path: '/',
96 | },
97 | home: {
98 | name: 'HomePage',
99 | path: '/',
100 | },
101 | ...
102 | },
103 | }
104 | ```
105 |
106 | ```javascript
107 | // config/router/index.ts
108 | import HomePage from 'pages/HomePage.vue'
109 |
110 | const routes = [
111 | {
112 | name: import.meta.env.ROUTER_HOME_NAME,
113 | path: import.meta.env.ROUTER_HOME_PATH,
114 | component: HomePage,
115 | },
116 | ...
117 | ]
118 |
119 | const router = createRouter({
120 | history: createWebHistory(import.meta.env.ROUTER_BASE_PATH),
121 | routes,
122 | sensitive: true,
123 | })
124 | ```
125 |
126 | ```html
127 |
128 |
137 |
138 |
139 |
140 |
141 | ```
142 |
143 | Imagine that what happend if you use the first solution to create vue-router information and change a name of path generator object. Are you sure that you changed all of them ?
144 |
145 |
lazy-loading
146 |
147 | In vue-router docs, it already introduced a simple way to create a lazy-loading route by using dynamic import. See code below and more in [vue-router docs](https://router.vuejs.org/guide/advanced/lazy-loading.html)
148 |
149 | ```javascript
150 | const routes = [
151 | {
152 | name: import.meta.env.ROUTER_HOME_NAME,
153 | path: import.meta.env.ROUTER_HOME_PATH,
154 | component: () => import('pages/HomePage.vue'),
155 | },
156 | ...
157 | ]
158 |
159 | const router = createRouter({
160 | history: createWebHistory(import.meta.env.ROUTER_BASE_PATH),
161 | routes,
162 | sensitive: true,
163 | })
164 | ```
165 |
166 |
Suspense
167 |
168 | Suspense is a loading resolver solution in Vue 3.x. Imagine that your page is loading the HomePage resource (by using import dynamic on route) or await an API requesting, and your internet connection is so bad. Bumb! You see a blank page or a current page in so long of time, and that's the time you have to show a loading page or a skeleton.
169 |
170 | In this section, I will discuss about handling the loading page when using lazy-loading routes.
171 |
172 | Continue the probplem above, we can resolve in two ways
173 |
174 | 1. Listen on Route and Listen on Hook
175 | Step by step like this
176 |
177 | - When a route init or change, the lisnter [beforeEach](https://router.vuejs.org/api/interfaces/router.html#beforeeach) will be fired. I will turn on load in this event.
178 | - When lazy-loading finish, the page component will active hooks. I will turn off loading screen at **created** hook
179 |
180 | route init/change > trigger beforeEach event > turn on loading screen > lazy-loading route finish > lifecycle hooks of page actived > created hook active > turn off loading screen.
181 |
182 | 2. Use Suspense
183 |
184 | In the first solution, we use router event and vue hook + store to keep flag of on/off the loading screen. It means we have to :
185 |
186 | - Define a isLoading flag in store.
187 | - Define the turn on script in beforeEach.
188 | - Define the turn of script in each page's created hook.
189 |
190 | I think that's run well, but not good for management.
191 |
192 | In the second solution, we will use Suspense to resolve loading screen with better management.
193 |
194 | To use Suspense for lazy-loading route, we need to customize something. The dynamic import syntax used for lazy-loading route in this version doesn't support right way for Suspense. So! In this project, I already customize a method support for lazy-loading routes to connect with Suspense right way. See the syntax below.
195 |
196 | ```javascript
197 | // config/router/index.js
198 | import LazyRoute from 'utils/LazyRoute'
199 | import PageLoader from 'components/PageLoader.vue'
200 | import ErrorComponent from 'components/ErrorComponent.vue'
201 |
202 | const lazyPage = LazyRoute.init({
203 | suspensible: false,
204 | loadingComponent: PageLoader,
205 | errorComponent: ErrorComponent,
206 | delay: 100,
207 | onError(error, retry, fail) {
208 | fail()
209 | },
210 | })
211 |
212 | const routes = [
213 | {
214 | name: import.meta.env.ROUTER_HOME_NAME,
215 | path: import.meta.env.ROUTER_HOME_PATH,
216 | component: lazyPage(() => import('pages/HomePage.vue')),
217 | },
218 | ...
219 | ]
220 | ```
221 |
222 | ```html
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 | ```
238 |
239 | Easy! And you're finish him. You created loading screen in just two files instead of multiples files like the first solution.
240 |
241 | NOTE: If you need to know detail how LazyRoute method works, you can open LazyRoute file and search it. Some keywords for researching: defineComponent, defineAsyncComponent, Render Functions.
242 |
243 |
Validate on route
244 |
245 | You can validate route params by using regex immediate in path defination, or if your regex ability isn't good, you can validate by some native JS methods like: split, splice, Number, ... and in that case, you need define your validation in the [meta options and use beforeEach event to execute it](https://router.vuejs.org/guide/advanced/meta.html#route-meta-fields). See code below
246 |
247 | ```javascript
248 | // It means the "title" param must be a string and the "id" param must be a number
249 | // /a-b-c-d-e1234 -> wrong
250 | // /a-b-c-d-e-1234 -> right (title is a-b-c-d-e, id is 1234)
251 | path: '/:title-:id(\\d+)'
252 | ```
253 |
254 | Some keywords for researching:
255 | [route's params](https://router.vuejs.org/guide/essentials/route-matching-syntax.html#custom-regex-in-params), [route's meta](https://router.vuejs.org/guide/advanced/meta.html#route-meta-fields)
256 |
257 |