..." }} />;
505 | }
506 | ```
507 |
508 | ### Vue.js
509 |
510 | ```html
511 |
512 |
513 |
514 |
523 | ```
524 |
525 | ## Conditional-Rendering
526 |
527 | ### React.js
528 |
529 | ```javascript
530 | function MyReactComponent() {
531 | const [isLoading, setLoading] = useState(true);
532 |
533 | return (
534 |
535 | {isLoading &&
Loading... }
536 | {isLoading ?
is loading
:
is loaded
}
537 |
538 | );
539 | }
540 | ```
541 |
542 | ### Vue.js
543 |
544 | ```html
545 |
546 |
547 |
548 |
Loading...
549 |
550 |
is loading
551 |
is loaded
552 |
553 |
554 |
555 |
562 | ```
563 |
564 | ## List-Rendering
565 |
566 | ### React.js
567 |
568 | ```javascript
569 | function MyReactComponent({ items }) {
570 | return (
571 |
572 | {items.map((item) => (
573 |
574 | {item.name}: {item.desc}
575 |
576 | ))}
577 |
578 | );
579 | }
580 | ```
581 |
582 | ### Vue.js
583 |
584 | ```html
585 |
586 |
587 |
588 | {{item.name}}: {{item.desc}}
589 |
590 |
591 |
592 |
599 | ```
600 |
601 | ## Render-Props
602 |
603 | ### React.js
604 |
605 | ```javascript
606 | function Modal({children, isOpen}) {
607 | const [isModalOpen, toggleModalOpen] = useState(isOpen);
608 |
609 | return (
610 |
611 | {type children === 'function' ? children(toggleModalOpen) : children}
612 |
)
613 | ;
614 | }
615 |
616 | Modal.propTypes = {
617 | isOpen: PropTypes.bool,
618 | children: PropTypes.oneOfType([PropTypes.string, PropTypes.element]).isRequired,
619 | }
620 | Modal.defaultProps = {
621 | isOpen: false,
622 | }
623 |
624 | ...
625 |
626 |
627 | {(toggleModalOpen) => {
628 |
629 |
...
630 |
toggleModalOpen(false)}>Cancel
631 |
632 | }}
633 |
634 | ```
635 |
636 | ### Vue.js (slot)
637 |
638 | ```html
639 |
640 |
641 |
642 |
643 |
644 |
665 |
666 | ...
667 |
668 |
669 |
670 | ...
671 | Close
672 |
673 |
674 | ```
675 |
676 | ## Lifecycle
677 |
678 | ### React.js
679 |
680 | - http://projects.wojtekmaj.pl/react-lifecycle-methods-diagram/
681 |
682 | #### Class component
683 |
684 | ```javascript
685 | class MyReactComponent extends React.Component {
686 | static getDerivedStateFromProps(props, state) {}
687 | componentDidMount() {}
688 | shouldComponentUpdate(nextProps, nextState) {}
689 | getSnapshotBeforeUpdate(prevProps, prevState) {}
690 | componentDidUpdate(prevProps, prevState) {}
691 | componentWillUnmount() {}
692 |
693 | render() {
694 | return
Hello World
;
695 | }
696 | }
697 | ```
698 |
699 | #### Function component
700 |
701 | ```javascript
702 | function MyReactComponent() {
703 | // componentDidMount
704 | useEffect(() => {}, []);
705 |
706 |
707 | // componentDidUpdate + componentDidMount
708 | useEffect(() => {});
709 |
710 | // componentWillUnmount
711 | useEffect(() => {
712 | return () => {...}
713 | }, []);
714 |
715 | // runs synchronously after a render but before the screen is updated
716 | useLayoutEffect(() => {}, []);
717 |
718 | return
Hello World
;
719 | }
720 | ```
721 |
722 | ### Vue.js
723 |
724 | - https://vuejs.org/v2/guide/instance.html#Lifecycle-Diagram
725 |
726 | ```html
727 |
728 | Hello World
729 |
730 |
742 | ```
743 |
744 | ## Error-Handling
745 |
746 | ### React.js
747 |
748 | ```javascript
749 | class ErrorBoundary extends React.Component {
750 | state = { hasError: false };
751 |
752 | static getDerivedStateFromError(error) {
753 | // Update state so the next render will show the fallback UI.
754 | return { hasError: true };
755 | }
756 |
757 | componentDidCatch(error, errorInfo) {}
758 |
759 | render() {
760 | if (this.state.hasError) return
Something went wrong. ;
761 | return this.props.children;
762 | }
763 | }
764 |
765 | ...
766 |
767 |
768 |
769 |
770 | ```
771 |
772 | ### Vue.js
773 |
774 | ```javascript
775 | const vm = new Vue({
776 | data: {
777 | error: "",
778 | },
779 | errorCaptured: function(err, component, details) {
780 | error = err.toString();
781 | }
782 | }
783 | ```
784 |
785 | ## Ref
786 |
787 | ### React.js
788 |
789 | #### Class component
790 |
791 | ```javascript
792 | class AutofocusInput extends React.Component {
793 | constructor(props) {
794 | super(props);
795 | this.ref = React.createRef();
796 | }
797 |
798 | state = {
799 | content: "",
800 | };
801 |
802 | componentDidMount() {
803 | this.ref.current.focus();
804 | }
805 |
806 | setContent = (e) => {
807 | this.setState({ content: e.target.value });
808 | };
809 |
810 | render() {
811 | return (
812 |
818 | );
819 | }
820 | }
821 | ```
822 |
823 | #### Function component
824 |
825 | ```javascript
826 | function AutofocusInput() {
827 | const [content, setContent] = useState("");
828 | const ref = useRef(null);
829 |
830 | useEffect(() => {
831 | if (ref && ref.current) {
832 | ref.current.focus();
833 | }
834 | }, []);
835 |
836 | return (
837 |
setContent(e.target.value)}
842 | />
843 | );
844 | }
845 | ```
846 |
847 | ### Vue.js
848 |
849 | ```html
850 |
851 |
852 |
853 |
864 | ```
865 |
866 | ## Performance-Optimization
867 |
868 | ### React.js
869 |
870 | #### PureComponent
871 |
872 | ```javascript
873 | class MyReactComponent extends React.PureComponent {
874 | ...
875 | }
876 | ```
877 |
878 | #### shouldComponentUpdate
879 |
880 | ```javascript
881 | class MyReactComponent extends React.Component {
882 | shouldComponentUpdate(nextProps) {...}
883 |
884 | ...
885 | }
886 | ```
887 |
888 | ### React.memo
889 |
890 | ```javascript
891 | export default React.memo(
892 | MyReactComponent,
893 | (prevProps, nextProps) => {
894 | ...
895 | }
896 | );
897 | ```
898 |
899 | ### useMemo
900 |
901 | ```javascript
902 | export default function MyReactComponent() {
903 | return React.useMemo(() => {
904 | return
...
;
905 | }, []);
906 | }
907 | ```
908 |
909 | ### useCallback
910 |
911 | ```javascript
912 | function MyItem({ item, handleDelete }) {
913 | const handleClick = useCallback(() => handleDelete(item), [
914 | item,
915 | handleDelete,
916 | ]);
917 |
918 | return
{item.name} ;
919 | }
920 | ```
921 |
922 | ### Vue.js
923 |
924 | #### v:once
925 |
926 | ```html
927 |
This will never change: {{msg}}
928 | ```
929 |
930 | #### functional component
931 |
932 | - https://vuejs.org/v2/guide/render-function.html#Functional-Components
933 |
934 | ```html
935 |
936 | Hello {{ name }}
937 |
938 |
946 | ```
947 |
948 | #### keep-alive component
949 |
950 | - https://vuejs.org/v2/api/#keep-alives
951 |
952 | ```html
953 |
954 |
955 |
956 | ```
957 |
958 | ---
959 |
960 | ## Reference
961 |
962 | - [React.js](https://reactjs.org/docs/getting-started.html)
963 | - [Vue.js](https://vuejs.org/v2/guide/#Getting-Started)
964 | - [Vue and React Side by Side](https://medium.com/myriatek/vue-and-react-side-by-side-55d02b9fb222)
965 | - [I created the exact same app in React and Vue. Here are the differences](https://medium.com/javascript-in-plain-english/i-created-the-exact-same-app-in-react-and-vue-here-are-the-differences-2019-edition-42ba2cab9e56)
966 | - [Few Tips to Optimizing Performance of React Project](https://dev.to/oahehc/few-tips-to-optimizing-performance-of-react-project-5h25)
967 | - [5 Extremely Easy ways to drastically improve your VueJS app’s speed](https://dev.to/veebuv/5-extremely-easy-ways-to-drastically-improve-your-vuejs-app-s-speed-5k0)
968 |
--------------------------------------------------------------------------------
/DevTools.md:
--------------------------------------------------------------------------------
1 | # DevTools
2 |
3 | ### React.js
4 |
5 | - React: https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi
6 | - Redux: https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd
7 |
8 | ### Vue.js
9 |
10 | - Vue & Vuex: https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React-Vue-Comparison
2 |
3 |
4 | This repo is for someone who already familiar with React.js or Vue.js, and wants to find out the relative syntax in another framework.
5 |
6 | | | ⭐️ | VERSION | OPEN ISSUES & PR | DOWNLOADS/wk |
7 | | :--- | ---: | :---: | ---: | ---: |
8 | | React: [npm](https://www.npmjs.com/package/react) [gh](https://github.com/facebook/react) [doc](https://reactjs.org/docs/getting-started.html) | 197,796 | 18.2.0 | 1,090 | 14,355,288
9 | Vue: [npm](https://www.npmjs.com/package/vue) [gh](https://github.com/vuejs/vue) [doc](https://vuejs.org/v2/guide/l) | 200,728 | 3.2.45 | 587 | 3,150,797
10 | Next.js: [npm](https://www.npmjs.com/package/next) [gh](https://github.com/vercel/next.js) [doc](https://nextjs.org/docs/getting-started) | 96,491 | 13.0.3 | 1,555 | 2,871,321
11 | Nuxt.js: [npm](https://www.npmjs.com/package/nuxt) [gh](https://github.com/nuxt/nuxt.js) [doc](https://nuxtjs.org/guide) | 41,606 | 3.0.0 | 511 | 401,488
12 | React-Router: [npm](https://www.npmjs.com/package/react-router) [gh](https://github.com/remix-run/react-router) [doc](https://reactrouter.com/) | 48,817 | 6.4.3 | 118 | 7,118,939
13 | Vue-Router: [npm](https://www.npmjs.com/package/vue-router) [gh](https://github.com/vuejs/vue-router) [doc](https://router.vuejs.org/guide) | 18,903 | 4.1.6 | 109 | 1,946,617
14 | redux: [npm](https://www.npmjs.com/package/redux) [gh](https://github.com/reduxjs/redux) [doc](https://redux.js.org/introduction/getting-started) | 58,890 | 4.2.0 | 56 | 6,901,716
15 | react-redux: [npm](https://www.npmjs.com/package/react-redux) [gh](https://github.com/reduxjs/react-redux) [doc](https://react-redux.js.org/introduction/quick-start) | 22,456 | 8.0.5 | 13 | 5,212,531
16 | vuex: [npm](https://www.npmjs.com/package/vuex) [gh](https://github.com/vuejs/vuex) [doc](https://vuex.vuejs.org/guide/) | 27,876 | 4.1.0 | 118 | 1,485,136 |
17 |
18 |
19 | _Update: 2022/11/17_
20 |
21 |
22 | ---
23 |
24 | ## Contents
25 |
26 | ### [React.js vs Vue.js](/CORE.md)
27 |
28 |
29 | - [Render](/CORE.md#render)
30 | - [Basic-Component](/CORE.md#basic-component)
31 | - [Prop](/CORE.md#prop)
32 | - [Event-Binding](/CORE.md#event-binding)
33 | - [Custom-Event](/CORE.md#custom-event)
34 | - [State](/CORE.md#state)
35 | - [Change-State](/CORE.md#change-state)
36 | - [Two-Way-Binding(Vue.js only)](/CORE.md#two-way-binding)
37 | - [Compute](/CORE.md#compute)
38 | - [Watch](/CORE.md#watch)
39 | - [Children-and-Slot](/CORE.md#children-and-slot)
40 | - [Render-HTML](/CORE.md#render-html)
41 | - [Conditional-Rendering](/CORE.md#conditional-rendering)
42 | - [List-Rendering](/CORE.md#list-rendering)
43 | - [Render-Props](/CORE.md#render-props)
44 | - [Lifecycle](/CORE.md#lifecycle)
45 | - [Error-Handling](/CORE.md#error-handling)
46 | - [Ref](/CORE.md#ref)
47 | - [Performance-Optimization](/CORE.md#performance-optimization)
48 |
49 | ### [Next.js vs Nuxt.js](/SSR.md)
50 |
51 |
52 | - [Assets](/SSR.md#assets)
53 | - [Basic-Routes](/SSR.md#basic-routes)
54 | - [Dynamic-Routes](/SSR.md#dynamic-routes)
55 | - [Link](/SSR.md#link)
56 | - [Fetch-On-Server](/SSR.md#fetch-on-server)
57 | - [Layout](/SSR.md#layout)
58 | - [Error-Page](/SSR.md#error-page)
59 | - [Meta-Tag](/SSR.md#meta-tag)
60 | - [Context](/SSR.md#context)
61 |
62 | ### Tools
63 |
64 |
65 | - [CLI](/CLI.md)
66 | - [DevTools](/DevTools.md)
67 |
68 | ### [React-Router vs Vue-Router](/ROUTER.md)
69 |
70 |
71 | - [Basic-Routing](/ROUTER.md#Basic-Routing)
72 | - [Dynamic-Routing](/ROUTER.md#Dynamic-Routing)
73 | - [Nested-Routing](/ROUTER.md#Nested-Routing)
74 | - [Link](/ROUTER.md#Link)
75 | - [NavLink](/ROUTER.md#NavLink)
76 | - [Get-Location](/ROUTER.md#Get-Location)
77 | - [Push](/ROUTER.md#Push)
78 | - [Replace](/ROUTER.md#Replace)
79 | - [Redirect](/ROUTER.md#Redirect)
80 | - [Event](/ROUTER.md#Event)
81 | - [Scroll](/ROUTER.md#Scroll)
82 | - [Lazy-Loading-and-Code-Splitting](/ROUTER.md#Lazy-Loading-and-Code-Splitting)
83 |
84 | ### [Redux vs Vuex](/STATE_MANAGEMENT.md)
85 |
86 |
87 | - [Create-Store](/STATE_MANAGEMENT.md#Create-Store)
88 | - [Action](/STATE_MANAGEMENT.md#Action)
89 | - [Async-Action](/STATE_MANAGEMENT.md#Async-Action)
90 | - [Reducer | Mutation](/STATE_MANAGEMENT.md#Reducer-or-Mutation)
91 | - [Combine-Reducers | Modules](/STATE_MANAGEMENT.md#Combine-Reducers-or-Modules)
92 | - [Connect-with-Component](/STATE_MANAGEMENT.md#Connect-with-Component)
93 | - [Middleware | Plugin](/STATE_MANAGEMENT.md#Middleware-or-Plugin)
94 | - [Selector | Getter](/STATE_MANAGEMENT.md#Selector-or-Getter)
95 | - [DevTools](/STATE_MANAGEMENT.md#DevTools)
96 |
97 |
98 | ---
99 |
100 | ## Reference
101 |
102 |
103 | - [React.js](https://reactjs.org/docs/getting-started.html)
104 | - [Next.js](https://nextjs.org/docs/getting-started)
105 | - [React Router](https://reacttraining.com/react-router/web/guides/quick-start)
106 | - [Vue.js](https://vuejs.org/v2/guide/#Getting-Started)
107 | - [Nuxt.js](https://nuxtjs.org/guide/installation)
108 | - [Vue Router](https://router.vuejs.org/guide/)
109 | - [Redux](https://redux.js.org/introduction/getting-started)
110 | - [React-Redux](https://react-redux.js.org/introduction/quick-start)
111 | - [Reselect](https://github.com/reduxjs/reselect)
112 | - [Vuex](https://vuex.vuejs.org/guide/)
113 |
--------------------------------------------------------------------------------
/ROUTER.md:
--------------------------------------------------------------------------------
1 | # Router: React-Router & Vue-Router
2 |
3 | ## Basic-Routing
4 |
5 | ### React-Router
6 |
7 | ```js
8 | import { BrowserRouter, Switch, Route } from 'react-router-dom';
9 |
10 | export default function App() {
11 | return (
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | );
21 | }
22 | ```
23 |
24 | ### Vue-Router
25 |
26 | ```js
27 | const routes = [
28 | { path: '/foo', component: Foo },
29 | { path: '/bar', component: Bar },
30 | ];
31 | const router = new VueRouter({
32 | mode: 'history',
33 | routes,
34 | });
35 | const app = new Vue({ router }).$mount('#app');
36 | ```
37 |
38 | ```html
39 |
40 |
41 |
42 | ```
43 |
44 | ## Dynamic-Routing
45 |
46 | ### React-Router
47 |
48 | ```js
49 | import { BrowserRouter, Route } from 'react-router-dom';
50 |
51 | function App() {
52 | return (
53 |
54 |
55 |
56 |
57 |
58 | );
59 | }
60 |
61 | ...
62 |
63 | import { useParams } from 'react-router-dom';
64 |
65 | function Contact() {
66 | let { id } = useParams();
67 |
68 | return ...;
69 | }
70 | ```
71 |
72 | ### Vue-Router
73 |
74 | ```js
75 | const router = new VueRouter({
76 | mode: 'history',
77 | routes: [{ path: '/contact/:id', component: Contact }],
78 | });
79 |
80 | export default {
81 | computed: {
82 | id() {
83 | return this.$route.params.id;
84 | },
85 | },
86 | };
87 | ```
88 |
89 | ## Nested-Routing
90 |
91 | ### React-Router
92 |
93 | ```js
94 | import { BrowserRouter, Route } from 'react-router-dom';
95 |
96 | const App = () => (
97 |
98 |
99 |
100 |
101 |
102 | );
103 |
104 | ...
105 |
106 | import { Route } from 'react-router-dom';
107 |
108 | const Tacos = ({ match }) => (
109 |
110 | {/* here's a nested Route, match.url helps us make a relative path */}
111 |
112 |
113 | );
114 | ```
115 |
116 | ### Vue-Router
117 |
118 | ```js
119 | const router = new VueRouter({
120 | routes: [
121 | {
122 | path: '/user/:id',
123 | component: User,
124 | children: [
125 | {
126 | path: 'profile',
127 | component: UserProfile,
128 | },
129 | {
130 | path: 'posts',
131 | component: UserPosts,
132 | },
133 | ],
134 | },
135 | ],
136 | });
137 |
138 | const User = {
139 | template: `
140 |
141 |
User {{ $route.params.id }}
142 |
143 |
144 | `,
145 | };
146 | ```
147 |
148 | ## Link
149 |
150 | ### React-Router
151 |
152 | ```js
153 |
161 | courses
162 |
163 | ```
164 |
165 | ### Vue-Router
166 |
167 | ```html
168 |
courses
169 | ```
170 |
171 | ## NavLink
172 |
173 | NavLink is used to display different style when current URL match to the link.
174 |
175 | ### React-Router
176 |
177 | ```js
178 |
179 | React
180 |
181 | ```
182 |
183 | ### Vue-Router
184 |
185 | `router-link` automatically gets the .router-link-active class when its target route is matched.
186 |
187 | ```html
188 |
vue
189 | ```
190 |
191 | ## Get-Location
192 |
193 | ### React-Router
194 |
195 | #### Function component
196 |
197 | ```js
198 | import { useLocation } from "react-router-dom";
199 |
200 | function App() {
201 | const location = useLocation();
202 |
203 | return ...;
204 | }
205 | ```
206 |
207 | #### Class component
208 |
209 | ```js
210 | import { withRouter } from "react-router";
211 |
212 | class App extends React.Component {
213 | static propTypes = {
214 | location: PropTypes.object.isRequired
215 | };
216 |
217 | render() {
218 | const { location } = this.props;
219 |
220 | return ...;
221 | }
222 | }
223 | export default withRouter(App);
224 | ```
225 |
226 | ### Vue-Router
227 |
228 | ```js
229 | export default {
230 | computed: {
231 | path() {
232 | return this.$route.path;
233 | },
234 | params() {
235 | return this.$route.params;
236 | },
237 | query() {
238 | return this.$route.query;
239 | },
240 | hash() {
241 | return this.$route.hash;
242 | },
243 | fullPath() {
244 | return this.$route.fullPath;
245 | },
246 | },
247 | };
248 | ```
249 |
250 | ## Push
251 |
252 | ### React-Router
253 |
254 | ```js
255 | import { useHistory } from 'react-router-dom';
256 |
257 | function HomeButton() {
258 | const history = useHistory();
259 |
260 | function handleClick() {
261 | history.push('/home');
262 | }
263 |
264 | return (
265 |
266 | Go home
267 |
268 | );
269 | }
270 | ```
271 |
272 | ### Vue-Router
273 |
274 | ```js
275 | export default {
276 | methods: {
277 | toHome() {
278 | this.$router.push('/home');
279 | },
280 | toUser(id) {
281 | this.$router.push({ name: 'user', params: { userId: id } });
282 | },
283 | toRegister(id) {
284 | // /register?plan=private
285 | this.$router.push({ path: 'register', query: { plan: 'private' } });
286 | },
287 | },
288 | };
289 | ```
290 |
291 | ## Replace
292 |
293 | replacing the current entry instead of push a new entry onto the history stack.
294 |
295 | ### React-Router
296 |
297 | ```js
298 |
;
299 |
300 | // or
301 |
302 | const history = useHistory();
303 |
304 | function handleClick() {
305 | history.replace('/courses');
306 | }
307 | ```
308 |
309 | ### Vue-Router
310 |
311 | ```html
312 |
313 | ```
314 |
315 | or
316 |
317 | ```js
318 | export default {
319 | methods: {
320 | toHome() {
321 | this.$router.replace('/home');
322 | },
323 | },
324 | };
325 | ```
326 |
327 | ## Redirect
328 |
329 | ### React-Router
330 |
331 | ```html
332 |
333 |
334 | // push a new entry onto the history instead of replacing the current one.
335 |
336 | ```
337 |
338 | ### Vue-Router
339 |
340 | ```js
341 | const router = new VueRouter({
342 | routes: [{ path: '/a', redirect: { name: 'foo' } }],
343 | });
344 | ```
345 |
346 | ## Event
347 |
348 | ### React-Router
349 |
350 | #### Function component
351 |
352 | ```js
353 | import { useHistory } from 'react-router-dom';
354 |
355 | function App() {
356 | const history = useHistory();
357 |
358 | useEffect(() => {
359 | const unlisten = this.props.history.listen(...);
360 | return () => unlisten();
361 | }, [])
362 |
363 | return ...;
364 | }
365 | ```
366 |
367 | #### Class component
368 |
369 | ```js
370 | import { withRouter } from "react-router";
371 |
372 | class App extends React.Component {
373 | static propTypes = {
374 | history: PropTypes.object.isRequired
375 | };
376 |
377 | componentDidMount() {
378 | this.unlisten = this.props.history.listen(...);
379 | }
380 |
381 | componentWillUnmount() {
382 | if (this.unlisten && typeof this.unlisten === 'function') {
383 | this.unlisten();
384 | }
385 | }
386 |
387 | render() {
388 | return ...;
389 | }
390 | }
391 | export default withRouter(App);
392 | ```
393 |
394 | ### Vue-Router
395 |
396 | #### global
397 |
398 | ```js
399 | const router = new VueRouter({ ... })
400 |
401 | router.beforeEach((to, from, next) => { ... })
402 | router.afterEach((to, from) => { ... })
403 | ```
404 |
405 | #### by route
406 |
407 | ```js
408 | const router = new VueRouter({
409 | routes: [
410 | {
411 | path: '/foo',
412 | component: Foo,
413 | beforeEnter: (to, from, next) => { ... }
414 | }
415 | ]
416 | })
417 | ```
418 |
419 | ### by component
420 |
421 | ```js
422 | const Foo = {
423 | template: `...`,
424 | beforeRouteEnter (to, from, next) { ... },
425 | beforeRouteUpdate (to, from, next) { ... },
426 | beforeRouteLeave (to, from, next) { ... },
427 | }
428 | ```
429 |
430 | ## Scroll
431 |
432 | ### React-Router
433 |
434 | Because browsers are starting to handle the `default case` and apps have varying scrolling needs, `React-Router` don’t ship with default scroll management.
435 | _https://reacttraining.com/react-router/web/guides/scroll-restoration_
436 |
437 | ```js
438 | export default function ScrollToTop() {
439 | const { pathname } = useLocation();
440 |
441 | useEffect(() => {
442 | window.scrollTo(0, 0);
443 | }, [pathname]);
444 |
445 | return null;
446 | }
447 | ```
448 |
449 | ### Vue-Router
450 |
451 | ```js
452 | const router = new VueRouter({
453 | routes: [...],
454 | scrollBehavior (to, from, savedPosition) {
455 | // return desired position
456 | if (savedPosition) {
457 | return savedPosition
458 | } else {
459 | return { x: 0, y: 0 }
460 | }
461 | }
462 | })
463 | ```
464 |
465 | ## Lazy-Loading-and-Code-Splitting
466 |
467 | _If you are using Babel, you will need to add the [syntax-dynamic-import](https://babeljs.io/docs/en/babel-plugin-syntax-dynamic-import/) plugin so that Babel can properly parse the syntax._
468 |
469 | ### React-Router
470 |
471 | _https://github.com/gregberge/loadable-components_
472 |
473 | ```js
474 | import loadable from '@loadable/component';
475 |
476 | const LoadableComponent = loadable(() => import('./Dashboard.js'), {
477 | fallback:
,
478 | });
479 | ```
480 |
481 | ### Vue-Router
482 |
483 | ```js
484 | const Foo = () => import('./Foo.vue');
485 |
486 | const router = new VueRouter({
487 | routes: [{ path: '/foo', component: Foo }],
488 | });
489 | ```
490 |
--------------------------------------------------------------------------------
/SSR.md:
--------------------------------------------------------------------------------
1 | # SSR: Next.js & Nuxt.js
2 |
3 | ## Assets
4 |
5 | ### Next.js
6 |
7 | ```js
8 | /*
9 | |- public/
10 | |-- my-image.png
11 | */
12 | function MyImage() {
13 | return
;
14 | }
15 | ```
16 |
17 | ### Nuxt.js
18 |
19 | #### assets
20 |
21 | _By default, Nuxt uses vue-loader, file-loader and url-loader for strong assets serving._
22 |
23 | ```html
24 |
28 |
29 | ```
30 |
31 | #### static
32 |
33 | _automatically served_
34 |
35 | ```html
36 |
40 |
41 | ```
42 |
43 | ## Basic-Routes
44 |
45 | ### Next.js
46 |
47 | ```
48 | |- pages/
49 | |- index.js → href="/"
50 | |- blog/index.js → href="/blog"
51 | ```
52 |
53 | ### Nuxt.js
54 |
55 | ```
56 | |- pages/
57 | |- index.vue → href="/"
58 | |- blog/index.vue → href="/blog"
59 | ```
60 |
61 | ## Dynamic-Routes
62 |
63 | ### Next.js
64 |
65 | ```
66 | |- pages/
67 | |- blog/[slug].js → href="/blog/:slug" (eg. /blog/hello-world)
68 | |- [username]/[option].js → href="/:username/:option" (eg. /foo/settings)
69 | |- post/[...all].js → href="/post/*" (eg. /post/2020/id/title)
70 | ```
71 |
72 | ### Nuxt.js
73 |
74 | ```
75 | |- pages/
76 | |- blog/[slug].vue → href="/blog/:slug" (eg. /blog/hello-world)
77 | |- _username/_option.vue → href="/:username/:option" (eg. /foo/settings)
78 | ```
79 |
80 | ## Link
81 |
82 | ### Next.js
83 |
84 | ```js
85 | import Link from "next/link";
86 |
87 | function Home() {
88 | return (
89 |
90 |
Home
91 |
92 | );
93 | }
94 | ```
95 |
96 | ### Nuxt.js
97 |
98 | ```html
99 |
100 | Home page
101 |
102 | ```
103 |
104 | ## Fetch-On-Server
105 |
106 | ### Next.js
107 |
108 | _getInitialProps can only be used in the default export of every page_
109 |
110 | #### < Next.js 9.3
111 |
112 | ##### class component
113 |
114 | ```js
115 | import fetch from "isomorphic-unfetch";
116 |
117 | export default class Page extends React.Component {
118 | static async getInitialProps(ctx) {
119 | const res = await fetch(`https://.../data`);
120 | const data = await res.json();
121 |
122 | return { props: { data } };
123 | }
124 |
125 | render() {
126 | // Render data...
127 | }
128 | }
129 | ```
130 |
131 | ##### function component
132 |
133 | ```js
134 | import fetch from "isomorphic-unfetch";
135 |
136 | function Page({ data }) {
137 | // Render data...
138 | }
139 |
140 | Page.getInitialProps = async (ctx) => {
141 | const res = await fetch(`https://.../data`);
142 | const data = await res.json();
143 |
144 | return { props: { data } };
145 | };
146 | ```
147 |
148 | #### >= Next.js 9.3
149 |
150 | ```js
151 | import fetch from "isomorphic-unfetch";
152 |
153 | function Page({ data }) {
154 | // Render data...
155 | }
156 |
157 | export async function getServerSideProps() {
158 | const res = await fetch(`https://.../data`);
159 | const data = await res.json();
160 |
161 | return { props: { data } };
162 | }
163 |
164 | export default Page;
165 | ```
166 |
167 | ### Nuxt.js
168 |
169 | ```html
170 |
171 | Something went wrong 😭
172 | Loading...
173 |
174 |
{{ post.title }}
175 |
{{ post.body }}
176 |
Refresh
177 |
178 |
179 |
180 |
195 | ```
196 |
197 | ## Layout
198 |
199 | ### Next.js
200 |
201 | `./pages/_app.js`: automatically apply to all pages
202 |
203 | ```js
204 | export default function MyApp({ Component, pageProps }) {
205 | return (
206 |
207 |
208 |
209 |
210 |
211 | );
212 | }
213 | ```
214 |
215 | ### Nuxt.js
216 |
217 | `layouts/with-header-footer.vue`: create layout
218 |
219 | ```html
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 | ```
228 |
229 | `pages/index.vue`: apply layout
230 |
231 | ```html
232 |
233 |
234 |
235 |
240 | ```
241 |
242 | ## Error-Page
243 |
244 | ### Next.js
245 |
246 | `pages/_error.js`
247 |
248 | ```js
249 | function Error({ statusCode }) {
250 | return (
251 |
252 | {statusCode
253 | ? `An error ${statusCode} occurred on server`
254 | : "An error occurred on client"}
255 |
256 | );
257 | }
258 |
259 | Error.getInitialProps = ({ res, err }) => {
260 | const statusCode = res ? res.statusCode : err ? err.statusCode : 404;
261 | return { statusCode };
262 | };
263 |
264 | export default Error;
265 | ```
266 |
267 | ### Nuxt.js
268 |
269 | `layouts/error.vue`
270 |
271 | ```html
272 |
273 |
274 |
Page not found
275 | An error occurred
276 | Home page
277 |
278 |
279 |
280 |
286 | ```
287 |
288 | ## Meta-Tag
289 |
290 | ### Next.js
291 |
292 | ```js
293 | import Head from "next/head";
294 |
295 | function IndexPage() {
296 | return (
297 |
298 |
299 |
My page title
300 |
301 |
302 |
Hello world!
303 |
304 | );
305 | }
306 | ```
307 |
308 | ### Nuxt.js
309 |
310 | ```html
311 |
312 | {{ title }}
313 |
314 |
315 |
337 | ```
338 |
339 | ## Context
340 |
341 | ### Next.js
342 |
343 | _getInitialProps can only be used in the default export of every page_
344 |
345 | ```js
346 | function Page({ data }) {
347 | // Render data...
348 | }
349 |
350 | Page.getInitialProps = async (context) => {
351 | const { pathname, query, asPath, req, res, err } = context;
352 | // pathname - Current route. That is the path of the page in /pages
353 | // query - Query string section of URL parsed as an object
354 | // asPath - String of the actual path (including the query) shown in the browser
355 | // req - HTTP request object (server only)
356 | // res - HTTP response object (server only)
357 | // err - Error object if any error is encountered during the rendering
358 |
359 | return { props: { project: "next" } };
360 | };
361 | ```
362 |
363 | ### Nuxt.js
364 |
365 | ```js
366 | export default {
367 | asyncData(context) {
368 | // Universal keys
369 | const {
370 | app,
371 | store,
372 | route,
373 | params,
374 | query,
375 | env,
376 | isDev,
377 | isHMR,
378 | redirect,
379 | error,
380 | } = context;
381 | // Server-side
382 | if (process.server) {
383 | const { req, res, beforeNuxtRender } = context;
384 | }
385 | // Client-side
386 | if (process.client) {
387 | const { from, nuxtState } = context;
388 | }
389 |
390 | return { project: "nuxt" };
391 | },
392 | };
393 | ```
394 |
395 | ---
396 |
397 | ## Reference
398 |
399 | - [Next.js](https://nextjs.org/docs/getting-started)
400 | - [Nuxt.js](https://nuxtjs.org/guide/installation)
401 |
--------------------------------------------------------------------------------
/STATE_MANAGEMENT.md:
--------------------------------------------------------------------------------
1 | # State Management: Redux & Vuex
2 |
3 | ## Create Store
4 |
5 | ### Redux: https://redux.js.org/basics/store
6 |
7 | ```js
8 | import React from 'react';
9 | import { render } from 'react-dom';
10 | import { Provider } from 'react-redux';
11 | import { createStore } from 'redux';
12 | import todoApp from './reducers';
13 | import App from './components/App';
14 |
15 | const store = createStore(todoApp);
16 |
17 | render(
18 |
19 |
20 | ,
21 | document.getElementById('root')
22 | );
23 | ```
24 |
25 | ### Vuex: https://vuex.vuejs.org/guide/
26 |
27 | ```js
28 | const store = new Vuex.Store({
29 | state: { ... },
30 | mutations: { ... }
31 | })
32 |
33 | ...
34 |
35 | new Vue({
36 | el: '#app',
37 | store,
38 | });
39 | ```
40 |
41 | ## Action
42 |
43 | ### Redux: https://redux.js.org/basics/actions
44 |
45 | ```js
46 | const ADD_TODO = 'ADD_TODO';
47 |
48 | function addTodo(text) {
49 | return {
50 | type: ADD_TODO,
51 | text,
52 | };
53 | }
54 | ```
55 |
56 | ### Vuex: https://vuex.vuejs.org/guide/actions.html
57 |
58 | ```js
59 | const store = new Vuex.Store({
60 | actions: {
61 | increment(context) {
62 | context.commit('increment'); // commit a mutation to trigger state update
63 | },
64 | },
65 | });
66 | ```
67 |
68 | ## Async-Action
69 |
70 | ### Redux(redux-thunk): https://redux.js.org/advanced/async-actions
71 |
72 | ```js
73 | // apply redux-thunk
74 | import thunkMiddleware from 'redux-thunk'
75 |
76 | const store = createStore(
77 | rootReducer,
78 | applyMiddleware(thunkMiddleware)
79 | )
80 |
81 | ...
82 |
83 | export function fetchPosts() {
84 | return function (dispatch) {
85 | dispatch(requestPosts())
86 | return fetch('xxx')
87 | .then(response => response.json())
88 | .then(json => dispatch(receivePosts(json)))
89 | }
90 | }
91 | ```
92 |
93 | ### Vuex: https://vuex.vuejs.org/guide/actions.html
94 |
95 | ```js
96 | actions: {
97 | async fetchPosts ({ commit }) {
98 | commit('requestPosts');
99 | const res = await fetch('xxx');
100 | commit('receivePosts', res);
101 | },
102 | }
103 | ```
104 |
105 | ## Reducer-or-Mutation
106 |
107 | ### Redux(reducer): https://redux.js.org/basics/reducers
108 |
109 | ```js
110 | const initialState = {
111 | todos: [],
112 | };
113 |
114 | function todoApp(state = initialState, action) {
115 | switch (action.type) {
116 | case ADD_TODO:
117 | return {
118 | ...state,
119 | todos: [
120 | ...state.todos,
121 | {
122 | text: action.text,
123 | completed: false,
124 | },
125 | ],
126 | };
127 |
128 | default:
129 | return state;
130 | }
131 | }
132 | ```
133 |
134 | ### Vuex(mutation): https://vuex.vuejs.org/guide/mutations.html
135 |
136 | ```js
137 | const store = new Vuex.Store({
138 | mutations: {
139 | addTodo(state, payload) {
140 | state.todos = [...state.todos, { text: payload.text, completed: false }];
141 | },
142 | },
143 | });
144 | ```
145 |
146 | ## Combine-Reducers-or-Modules
147 |
148 | ### Redux(combine-reducers): https://redux.js.org/api/combinereducers
149 |
150 | ```js
151 | import { combineReducers } from 'redux';
152 |
153 | const reducers = combineReducers({
154 | reducerA,
155 | reducerB,
156 | });
157 |
158 | export default reducers;
159 | ```
160 |
161 | ### Vuex(modules): https://vuex.vuejs.org/guide/modules.html
162 |
163 | ```js
164 | const moduleA = {
165 | state: { ... },
166 | mutations: { ... },
167 | actions: { ... },
168 | getters: { ... }
169 | }
170 |
171 | const moduleB = {
172 | state: { ... },
173 | mutations: { ... },
174 | actions: { ... }
175 | }
176 |
177 | const store = new Vuex.Store({
178 | modules: {
179 | a: moduleA,
180 | b: moduleB
181 | }
182 | })
183 | ```
184 |
185 | ## Connect-with-Component
186 |
187 | ### Redux: https://redux.js.org/basics/usage-with-react
188 |
189 | ```js
190 | import { connect } from 'react-redux';
191 | import { addTodo } from '../actions';
192 | import TargetComp from '../components/TargetComp';
193 |
194 | // state
195 | const mapStateToProps = (state, ownProps) => {
196 | return {
197 | todos: state.todos,
198 | };
199 | };
200 |
201 | // action
202 | const mapDispatchToProps = (dispatch, ownProps) => {
203 | return {
204 | addTodo: text => {
205 | dispatch(addTodo(text));
206 | },
207 | };
208 | };
209 |
210 | const TargetContainer = connect(mapStateToProps, mapDispatchToProps)(TargetComp);
211 |
212 | export default TargetContainer;
213 | ```
214 |
215 | ### Vuex
216 |
217 | #### state: https://vuex.vuejs.org/guide/state.html
218 |
219 | ```js
220 | import { mapState } from 'vuex';
221 |
222 | export default {
223 | computed: {
224 | ...mapState(['count']),
225 | },
226 | };
227 | ```
228 |
229 | #### action: https://vuex.vuejs.org/guide/actions.html
230 |
231 | ```js
232 | import { mapActions } from 'vuex';
233 |
234 | export default {
235 | methods: {
236 | ...mapActions(['increment']),
237 | },
238 | };
239 | ```
240 |
241 | ## Middleware-or-Plugin
242 |
243 | ### Redux(middleware): https://redux.js.org/advanced/middleware
244 |
245 | ```js
246 | import { createStore, combineReducers, applyMiddleware } from 'redux';
247 |
248 | const logger = store => next => action => {
249 | console.log('dispatching', action);
250 | let result = next(action);
251 | console.log('next state', store.getState());
252 | return result;
253 | };
254 | const todoApp = combineReducers(reducers);
255 | const store = createStore(todoApp, applyMiddleware(logger));
256 | ```
257 |
258 | ### Vuex(plugin): https://vuex.vuejs.org/guide/plugins.html
259 |
260 | ```js
261 | const myPluginWithSnapshot = store => {
262 | let prevState = _.cloneDeep(store.state)
263 | store.subscribe((mutation, state) => {
264 | let nextState = _.cloneDeep(state)
265 |
266 | // compare `prevState` and `nextState`...
267 |
268 | // save state for next mutation
269 | prevState = nextState
270 | })
271 | }
272 |
273 | const store = new Vuex.Store({
274 | ...,
275 | plugins: process.env.NODE_ENV !== 'production' ? [myPluginWithSnapshot] : [],
276 | })
277 | ```
278 |
279 | ## Selector-or-Getter
280 |
281 | ### Redux(reselect): https://redux.js.org/recipes/computing-derived-data
282 |
283 | ```js
284 | import { createSelector } from 'reselect'
285 |
286 | const getTodos = state => state.todos
287 |
288 | export const getDoneTodos = createSelector(
289 | [getTodos],
290 | todos.filter(t => t.completed),
291 | )
292 |
293 | ...
294 |
295 | import { connect } from 'react-redux'
296 | import TodoList from '../components/TodoList'
297 | import { getDoneTodos } from '../selectors'
298 |
299 | const mapStateToProps = state => {
300 | return {
301 | doneTodos: getDoneTodos(state)
302 | }
303 | }
304 |
305 | const DoneTodoList = connect(mapStateToProps)(TodoList)
306 |
307 | export default DoneTodoList
308 | ```
309 |
310 | ### Vuex: https://vuex.vuejs.org/guide/getters.html
311 |
312 | ```js
313 | const store = new Vuex.Store({
314 | state: { ... },
315 | getters: {
316 | doneTodos: state => {
317 | return state.todos.filter(t => t.completed)
318 | }
319 | }
320 | })
321 |
322 | ...
323 |
324 | import { mapGetters } from 'vuex'
325 |
326 | export default {
327 | computed: {
328 | ...mapGetters(['doneTodos'])
329 | }
330 | }
331 | ```
332 |
333 | ## DevTools
334 |
335 | ### Redux
336 |
337 | https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd
338 |
339 | ### Vuex
340 |
341 | https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd
342 |
343 | ---
344 |
345 | ## Reference
346 |
347 | - [Redux](https://redux.js.org/introduction/getting-started)
348 | - [React-Redux](https://react-redux.js.org/introduction/quick-start)
349 | - [Reselect](https://github.com/reduxjs/reselect)
350 | - [Vuex](https://vuex.vuejs.org/guide/)
351 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-vue-comparison",
3 | "version": "1.0.0",
4 | "description": "This repo is for someone who already familiar with React.js or Vue.js, and wants to find out the relative syntax in another framework.",
5 | "scripts": {
6 | "postinstall": "patch-package",
7 | "sync": "node scripts/updateReadme.js"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git+https://github.com/oahehc/react-vue-comparison.git"
12 | },
13 | "keywords": [
14 | "react",
15 | "vue",
16 | "nextjs",
17 | "nuxtjs"
18 | ],
19 | "author": "oahehc@gmail.com",
20 | "license": "MIT",
21 | "bugs": {
22 | "url": "https://github.com/oahehc/react-vue-comparison/issues"
23 | },
24 | "homepage": "https://github.com/oahehc/react-vue-comparison#readme",
25 | "dependencies": {
26 | "axios": "^0.19.2",
27 | "json2md": "^1.7.0",
28 | "patch-package": "^6.2.2",
29 | "postinstall-postinstall": "^2.1.0",
30 | "puppeteer": "^3.3.0"
31 | },
32 | "prettier": {
33 | "printWidth": 120,
34 | "singleQuote": true,
35 | "trailingComma": "es5",
36 | "arrowParens": "avoid"
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/patches/json2md+1.7.0.patch:
--------------------------------------------------------------------------------
1 | diff --git a/node_modules/json2md/.DS_Store b/node_modules/json2md/.DS_Store
2 | new file mode 100644
3 | index 0000000..949796c
4 | Binary files /dev/null and b/node_modules/json2md/.DS_Store differ
5 | diff --git a/node_modules/json2md/lib/converters.js b/node_modules/json2md/lib/converters.js
6 | index 9ed0b4f..1359a5f 100644
7 | --- a/node_modules/json2md/lib/converters.js
8 | +++ b/node_modules/json2md/lib/converters.js
9 | @@ -117,7 +117,19 @@ converters.table = function (input, json2md) {
10 | }
11 |
12 | var header = " | " + input.headers.join(" | ") + " | ",
13 | - spaces = " | " + input.headers.map(function () {
14 | + spaces = " | " + input.headers.map(function (_, index) {
15 | + if (input.aligns && input.aligns[index]) {
16 | + switch (input.aligns[index]) {
17 | + case "center":
18 | + return ":---:";
19 | + case "right":
20 | + return "---:";
21 | + case "left":
22 | + return ":---";
23 | + default:
24 | + return "---";
25 | + }
26 | + }
27 | return "---";
28 | }).join(" | ") + " | ",
29 | data = " | " + input.rows.map(function (r) {
30 |
--------------------------------------------------------------------------------
/scripts/updateReadme.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | const path = require('path');
3 | const axios = require('axios');
4 | const puppeteer = require('puppeteer');
5 | const json2md = require('json2md');
6 |
7 | // README default content
8 | const title = [
9 | { h1: 'React-Vue-Comparison' },
10 | {
11 | p:
12 | 'This repo is for someone who already familiar with React.js or Vue.js, and wants to find out the relative syntax in another framework.',
13 | },
14 | ];
15 | const contents = [
16 | { h2: 'Contents' },
17 | { h3: '[React.js vs Vue.js](/CORE.md)' },
18 | {
19 | ul: [
20 | '[Render](/CORE.md#render)',
21 | '[Basic-Component](/CORE.md#basic-component)',
22 | '[Prop](/CORE.md#prop)',
23 | '[Event-Binding](/CORE.md#event-binding)',
24 | '[Custom-Event](/CORE.md#custom-event)',
25 | '[State](/CORE.md#state)',
26 | '[Change-State](/CORE.md#change-state)',
27 | '[Two-Way-Binding(Vue.js only)](/CORE.md#two-way-binding)',
28 | '[Compute](/CORE.md#compute)',
29 | '[Watch](/CORE.md#watch)',
30 | '[Children-and-Slot](/CORE.md#children-and-slot)',
31 | '[Render-HTML](/CORE.md#render-html)',
32 | '[Conditional-Rendering](/CORE.md#conditional-rendering)',
33 | '[List-Rendering](/CORE.md#list-rendering)',
34 | '[Render-Props](/CORE.md#render-props)',
35 | '[Lifecycle](/CORE.md#lifecycle)',
36 | '[Error-Handling](/CORE.md#error-handling)',
37 | '[Ref](/CORE.md#ref)',
38 | '[Performance-Optimization](/CORE.md#performance-optimization)',
39 | ],
40 | },
41 | { h3: '[Next.js vs Nuxt.js](/SSR.md)' },
42 | {
43 | ul: [
44 | '[Assets](/SSR.md#assets)',
45 | '[Basic-Routes](/SSR.md#basic-routes)',
46 | '[Dynamic-Routes](/SSR.md#dynamic-routes)',
47 | '[Link](/SSR.md#link)',
48 | '[Fetch-On-Server](/SSR.md#fetch-on-server)',
49 | '[Layout](/SSR.md#layout)',
50 | '[Error-Page](/SSR.md#error-page)',
51 | '[Meta-Tag](/SSR.md#meta-tag)',
52 | '[Context](/SSR.md#context)',
53 | ],
54 | },
55 | { h3: 'Tools' },
56 | {
57 | ul: ['[CLI](/CLI.md)', '[DevTools](/DevTools.md)'],
58 | },
59 | { h3: '[React-Router vs Vue-Router](/ROUTER.md)' },
60 | {
61 | ul: [
62 | '[Basic-Routing](/ROUTER.md#Basic-Routing)',
63 | '[Dynamic-Routing](/ROUTER.md#Dynamic-Routing)',
64 | '[Nested-Routing](/ROUTER.md#Nested-Routing)',
65 | '[Link](/ROUTER.md#Link)',
66 | '[NavLink](/ROUTER.md#NavLink)',
67 | '[Get-Location](/ROUTER.md#Get-Location)',
68 | '[Push](/ROUTER.md#Push)',
69 | '[Replace](/ROUTER.md#Replace)',
70 | '[Redirect](/ROUTER.md#Redirect)',
71 | '[Event](/ROUTER.md#Event)',
72 | '[Scroll](/ROUTER.md#Scroll)',
73 | '[Lazy-Loading-and-Code-Splitting](/ROUTER.md#Lazy-Loading-and-Code-Splitting)',
74 | ],
75 | },
76 | { h3: '[Redux vs Vuex](/STATE_MANAGEMENT.md)' },
77 | {
78 | ul: [
79 | '[Create-Store](/STATE_MANAGEMENT.md#Create-Store)',
80 | '[Action](/STATE_MANAGEMENT.md#Action)',
81 | '[Async-Action](/STATE_MANAGEMENT.md#Async-Action)',
82 | '[Reducer | Mutation](/STATE_MANAGEMENT.md#Reducer-or-Mutation)',
83 | '[Combine-Reducers | Modules](/STATE_MANAGEMENT.md#Combine-Reducers-or-Modules)',
84 | '[Connect-with-Component](/STATE_MANAGEMENT.md#Connect-with-Component)',
85 | '[Middleware | Plugin](/STATE_MANAGEMENT.md#Middleware-or-Plugin)',
86 | '[Selector | Getter](/STATE_MANAGEMENT.md#Selector-or-Getter)',
87 | '[DevTools](/STATE_MANAGEMENT.md#DevTools)',
88 | ],
89 | },
90 | { p: '---' },
91 | ];
92 | const reference = [
93 | { h2: 'Reference' },
94 | {
95 | ul: [
96 | '[React.js](https://reactjs.org/docs/getting-started.html)',
97 | '[Next.js](https://nextjs.org/docs/getting-started)',
98 | '[React Router](https://reacttraining.com/react-router/web/guides/quick-start)',
99 | '[Vue.js](https://vuejs.org/v2/guide/#Getting-Started)',
100 | '[Nuxt.js](https://nuxtjs.org/guide/installation)',
101 | '[Vue Router](https://router.vuejs.org/guide/)',
102 | '[Redux](https://redux.js.org/introduction/getting-started)',
103 | '[React-Redux](https://react-redux.js.org/introduction/quick-start)',
104 | '[Reselect](https://github.com/reduxjs/reselect)',
105 | '[Vuex](https://vuex.vuejs.org/guide/)',
106 | ],
107 | },
108 | ];
109 |
110 | const repos = {
111 | react: {
112 | name: 'React',
113 | ghApi: 'https://api.github.com/search/repositories?q=react+in:name+user:facebook',
114 | npmUrl: 'https://www.npmjs.com/package/react',
115 | ghUrl: 'https://github.com/facebook/react',
116 | doc: 'https://reactjs.org/docs/getting-started.html',
117 | },
118 | vue: {
119 | name: 'Vue',
120 | ghApi: 'https://api.github.com/search/repositories?q=vue+in:name+user:vuejs',
121 | npmUrl: 'https://www.npmjs.com/package/vue',
122 | ghUrl: 'https://github.com/vuejs/vue',
123 | doc: 'https://vuejs.org/v2/guide/l',
124 | },
125 | 'next.js': {
126 | name: 'Next.js',
127 | ghApi: 'https://api.github.com/search/repositories?q=next+in:name+user:vercel',
128 | npmUrl: 'https://www.npmjs.com/package/next',
129 | ghUrl: 'https://github.com/vercel/next.js',
130 | doc: 'https://nextjs.org/docs/getting-started',
131 | },
132 | 'nuxt.js': {
133 | name: 'Nuxt.js',
134 | ghApi: 'https://api.github.com/search/repositories?q=nuxt+in:name+user:nuxt',
135 | npmUrl: 'https://www.npmjs.com/package/nuxt',
136 | ghUrl: 'https://github.com/nuxt/nuxt.js',
137 | doc: 'https://nuxtjs.org/guide',
138 | },
139 | 'react-router': {
140 | name: 'React-Router',
141 | ghApi: 'https://api.github.com/search/repositories?q=react-router+in:name+user:remix-run',
142 | npmUrl: 'https://www.npmjs.com/package/react-router',
143 | ghUrl: 'https://github.com/remix-run/react-router',
144 | doc: 'https://reactrouter.com/',
145 | },
146 | 'vue-router': {
147 | name: 'Vue-Router',
148 | ghApi: 'https://api.github.com/search/repositories?q=vue-router+in:name+user:vuejs',
149 | npmUrl: 'https://www.npmjs.com/package/vue-router',
150 | ghUrl: 'https://github.com/vuejs/vue-router',
151 | doc: 'https://router.vuejs.org/guide',
152 | },
153 | redux: {
154 | name: 'redux',
155 | ghApi: 'https://api.github.com/search/repositories?q=redux+in:name+user:reduxjs',
156 | npmUrl: 'https://www.npmjs.com/package/redux',
157 | ghUrl: 'https://github.com/reduxjs/redux',
158 | doc: 'https://redux.js.org/introduction/getting-started',
159 | },
160 | 'react-redux': {
161 | name: 'react-redux',
162 | ghApi: 'https://api.github.com/search/repositories?q=react-redux+in:name+user:reduxjs',
163 | npmUrl: 'https://www.npmjs.com/package/react-redux',
164 | ghUrl: 'https://github.com/reduxjs/react-redux',
165 | doc: 'https://react-redux.js.org/introduction/quick-start',
166 | },
167 | vuex: {
168 | name: 'vuex',
169 | ghApi: 'https://api.github.com/search/repositories?q=vuex+in:name+user:vuejs',
170 | npmUrl: 'https://www.npmjs.com/package/vuex',
171 | ghUrl: 'https://github.com/vuejs/vuex',
172 | doc: 'https://vuex.vuejs.org/guide/',
173 | },
174 | };
175 |
176 | function getToday() {
177 | const now = new Date();
178 | return `${now.getFullYear()}/${now.getMonth() + 1}/${now.getDate()}`;
179 | }
180 | function logger(...args) {
181 | console.log(`[${new Date().toISOString()}] `, ...args);
182 | }
183 | function getRowTitle(key) {
184 | if (!repos[key]) return '';
185 |
186 | const info = repos[key];
187 | return `${info.name}: [npm](${info.npmUrl}) [gh](${info.ghUrl}) [doc](${info.doc})`;
188 | }
189 |
190 | function generateTable(info) {
191 | return [
192 | {
193 | table: {
194 | headers: ['', '⭐️', 'VERSION', 'OPEN ISSUES & PR', 'DOWNLOADS/wk'],
195 | aligns: ['left', 'right', 'center', 'right', 'right'],
196 | rows: Object.keys(repos).map(key => [
197 | getRowTitle(key),
198 | info[key].stars,
199 | info[key].version,
200 | info[key].issues,
201 | info[key].wkDownload,
202 | ]),
203 | },
204 | },
205 | { p: `_Update: ${getToday()}_` },
206 | { p: '---' },
207 | ];
208 | }
209 | function generateMD(table) {
210 | const readme = [...title, ...table, ...contents, ...reference];
211 | return json2md(readme);
212 | }
213 |
214 | (async function load() {
215 | const output = Object.keys(repos).reduce((res, name) => ({
216 | ...res,
217 | [name]: {
218 | stars: '?',
219 | version: '?',
220 | issues: '?',
221 | wkDownload: '?',
222 | }
223 | }), {})
224 |
225 | try {
226 | logger('load GitHub Info');
227 | const requests = Object.values(repos).map(({ ghApi }) => axios.get(ghApi));
228 | const results = await Promise.all(requests);
229 | results.forEach(({ data }) => {
230 | if (data && data.items && data.items[0]) {
231 | const { name, stargazers_count, open_issues_count } = data.items[0];
232 | if (name) {
233 | output[name] = {
234 | stars: Number(stargazers_count).toLocaleString(),
235 | issues: Number(open_issues_count).toLocaleString(),
236 | };
237 | }
238 | }
239 | });
240 | } catch (e) {
241 | logger('get github info fail:', e);
242 | }
243 |
244 | try {
245 | logger('load NPM Info');
246 | const browser = await puppeteer.launch({ headless: true });
247 | const page = await browser.newPage();
248 | for (let k in repos) {
249 | const repo = repos[k];
250 | await page.goto(repo.npmUrl);
251 |
252 | const info = await page.evaluate(() => {
253 | function getElementByTitle(title, selector) {
254 | const elements = document.querySelectorAll(selector);
255 | let ele = null;
256 | for (let i = 0; i < elements.length; i++) {
257 | if (elements[i].textContent.includes(title)) {
258 | ele = elements[i];
259 | break;
260 | }
261 | }
262 | return ele;
263 | }
264 |
265 | const wkDownloadTitle = getElementByTitle("Weekly Downloads", "h3");
266 | let wkDownload = "?";
267 | if (wkDownloadTitle && wkDownloadTitle.nextSibling) {
268 | const ele = wkDownloadTitle.nextSibling.querySelector('p');
269 | if (ele) {
270 | wkDownload = ele.innerText;
271 | }
272 | }
273 | const versionTitle = getElementByTitle("Version", "h3");
274 | let version = "?";
275 | if (versionTitle && versionTitle.nextSibling) {
276 | version = versionTitle.nextSibling.innerText;
277 | }
278 | return {
279 | wkDownload,
280 | version,
281 | };
282 | });
283 |
284 | if (output[k]) {
285 | output[k] = {
286 | ...output[k],
287 | ...info,
288 | };
289 | }
290 | }
291 | await browser.close();
292 |
293 | logger('generate README');
294 | const table = generateTable(output);
295 | const filePath = path.resolve(__dirname, `../README.md`);
296 | fs.writeFile(filePath, generateMD(table), 'utf8', err => {
297 | if (err) throw err;
298 | logger('finish');
299 | });
300 | } catch (e) {
301 | logger('get npm info fail:', e);
302 | }
303 | })();
--------------------------------------------------------------------------------
/template/next-template/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 |
6 | # testing
7 | /coverage
8 |
9 | # production
10 | /build
11 | /dist
12 | /.next
13 |
14 | # misc
15 | .DS_Store
16 | .env
17 | npm-debug.log*
18 | yarn-debug.log*
19 | yarn-error.log*
20 |
--------------------------------------------------------------------------------
/template/next-template/README.md:
--------------------------------------------------------------------------------
1 | This project was bootstrapped with [Create Next App](https://github.com/segmentio/create-next-app).
2 |
3 | Find the most recent version of this guide at [here](https://github.com/segmentio/create-next-app/blob/master/lib/templates/default/README.md). And check out [Next.js repo](https://github.com/zeit/next.js) for the most up-to-date info.
4 |
5 | ## Table of Contents
6 |
7 | - [Questions? Feedback?](#questions-feedback)
8 | - [Folder Structure](#folder-structure)
9 | - [Available Scripts](#available-scripts)
10 | - [npm run dev](#npm-run-dev)
11 | - [npm run build](#npm-run-build)
12 | - [npm run start](#npm-run-start)
13 | - [Using CSS](#using-css)
14 | - [Adding Components](#adding-components)
15 | - [Fetching Data](#fetching-data)
16 | - [Custom Server](#custom-server)
17 | - [Syntax Highlighting](#syntax-highlighting)
18 | - [Using the `static` Folder](#using-the-static-folder)
19 | - [Deploy to Now](#deploy-to-now)
20 | - [Something Missing?](#something-missing)
21 |
22 | ## Questions? Feedback?
23 |
24 | Check out [Next.js FAQ & docs](https://github.com/zeit/next.js#faq) or [let us know](https://github.com/segmentio/create-next-app/issues) your feedback.
25 |
26 | ## Folder Structure
27 |
28 | After creating an app, it should look something like:
29 |
30 | ```
31 | .
32 | ├── README.md
33 | ├── components
34 | │ ├── head.js
35 | │ └── nav.js
36 | ├── next.config.js
37 | ├── node_modules
38 | │ ├── [...]
39 | ├── package.json
40 | ├── pages
41 | │ └── index.js
42 | ├── static
43 | │ └── favicon.ico
44 | └── yarn.lock
45 | ```
46 |
47 | Routing in Next.js is based on the file system, so `./pages/index.js` maps to the `/` route and
48 | `./pages/about.js` would map to `/about`.
49 |
50 | The `./static` directory maps to `/static` in the `next` server, so you can put all your
51 | other static resources like images or compiled CSS in there.
52 |
53 | Out of the box, we get:
54 |
55 | - Automatic transpilation and bundling (with webpack and babel)
56 | - Hot code reloading
57 | - Server rendering and indexing of `./pages`
58 | - Static file serving. `./static/` is mapped to `/static/`
59 |
60 | Read more about [Next's Routing](https://github.com/zeit/next.js#routing)
61 |
62 | ## Available Scripts
63 |
64 | In the project directory, you can run:
65 |
66 | ### `npm run dev`
67 |
68 | Runs the app in the development mode.
69 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
70 |
71 | The page will reload if you make edits.
72 | You will also see any errors in the console.
73 |
74 | ### `npm run build`
75 |
76 | Builds the app for production to the `.next` folder.
77 | It correctly bundles React in production mode and optimizes the build for the best performance.
78 |
79 | ### `npm run start`
80 |
81 | Starts the application in production mode.
82 | The application should be compiled with \`next build\` first.
83 |
84 | See the section in Next docs about [deployment](https://github.com/zeit/next.js/wiki/Deployment) for more information.
85 |
86 | ## Using CSS
87 |
88 | [`styled-jsx`](https://github.com/zeit/styled-jsx) is bundled with next to provide support for isolated scoped CSS. The aim is to support "shadow CSS" resembling of Web Components, which unfortunately [do not support server-rendering and are JS-only](https://github.com/w3c/webcomponents/issues/71).
89 |
90 | ```jsx
91 | export default () => (
92 |
93 | Hello world
94 |
scoped!
95 |
108 |
109 | )
110 | ```
111 |
112 | Read more about [Next's CSS features](https://github.com/zeit/next.js#css).
113 |
114 | ## Adding Components
115 |
116 | We recommend keeping React components in `./components` and they should look like:
117 |
118 | ### `./components/simple.js`
119 |
120 | ```jsx
121 | const Simple = () =>
Simple Component
122 |
123 | export default Simple // don't forget to export default!
124 | ```
125 |
126 | ### `./components/complex.js`
127 |
128 | ```jsx
129 | import { Component } from 'react'
130 |
131 | class Complex extends Component {
132 | state = {
133 | text: 'World'
134 | }
135 |
136 | render() {
137 | const { text } = this.state
138 | return
Hello {text}
139 | }
140 | }
141 |
142 | export default Complex // don't forget to export default!
143 | ```
144 |
145 | ## Fetching Data
146 |
147 | You can fetch data in `pages` components using `getInitialProps` like this:
148 |
149 | ### `./pages/stars.js`
150 |
151 | ```jsx
152 | const Page = props =>
Next stars: {props.stars}
153 |
154 | Page.getInitialProps = async ({ req }) => {
155 | const res = await fetch('https://api.github.com/repos/zeit/next.js')
156 | const json = await res.json()
157 | const stars = json.stargazers_count
158 | return { stars }
159 | }
160 |
161 | export default Page
162 | ```
163 |
164 | For the initial page load, `getInitialProps` will execute on the server only. `getInitialProps` will only be executed on the client when navigating to a different route via the `Link` component or using the routing APIs.
165 |
166 | _Note: `getInitialProps` can **not** be used in children components. Only in `pages`._
167 |
168 | Read more about [fetching data and the component lifecycle](https://github.com/zeit/next.js#fetching-data-and-component-lifecycle)
169 |
170 | ## Custom Server
171 |
172 | Want to start a new app with a custom server? Run `create-next-app --example customer-server custom-app`
173 |
174 | Typically you start your next server with `next start`. It's possible, however, to start a server 100% programmatically in order to customize routes, use route patterns, etc
175 |
176 | This example makes `/a` resolve to `./pages/b`, and `/b` resolve to `./pages/a`:
177 |
178 | ```jsx
179 | const { createServer } = require('http')
180 | const { parse } = require('url')
181 | const next = require('next')
182 |
183 | const dev = process.env.NODE_ENV !== 'production'
184 | const app = next({ dev })
185 | const handle = app.getRequestHandler()
186 |
187 | app.prepare().then(() => {
188 | createServer((req, res) => {
189 | // Be sure to pass `true` as the second argument to `url.parse`.
190 | // This tells it to parse the query portion of the URL.
191 | const parsedUrl = parse(req.url, true)
192 | const { pathname, query } = parsedUrl
193 |
194 | if (pathname === '/a') {
195 | app.render(req, res, '/b', query)
196 | } else if (pathname === '/b') {
197 | app.render(req, res, '/a', query)
198 | } else {
199 | handle(req, res, parsedUrl)
200 | }
201 | }).listen(3000, err => {
202 | if (err) throw err
203 | console.log('> Ready on http://localhost:3000')
204 | })
205 | })
206 | ```
207 |
208 | Then, change your `start` script to `NODE_ENV=production node server.js`.
209 |
210 | Read more about [custom server and routing](https://github.com/zeit/next.js#custom-server-and-routing)
211 |
212 | ## Syntax Highlighting
213 |
214 | To configure the syntax highlighting in your favorite text editor, head to the [relevant Babel documentation page](https://babeljs.io/docs/editors) and follow the instructions. Some of the most popular editors are covered.
215 |
216 | ## Deploy to Now
217 |
218 | [now](https://zeit.co/now) offers a zero-configuration single-command deployment.
219 |
220 | 1. Install the `now` command-line tool either via the recommended [desktop tool](https://zeit.co/download) or via node with `npm install -g now`.
221 |
222 | 2. Run `now` from your project directory. You will see a **now.sh** URL in your output like this:
223 |
224 | ```
225 | > Ready! https://your-project-dirname-tpspyhtdtk.now.sh (copied to clipboard)
226 | ```
227 |
228 | Paste that URL into your browser when the build is complete, and you will see your deployed app.
229 |
230 | You can find more details about [`now` here](https://zeit.co/now).
231 |
232 | ## Something Missing?
233 |
234 | If you have ideas for how we could improve this readme or the project in general, [let us know](https://github.com/segmentio/create-next-app/issues) or [contribute some!](https://github.com/segmentio/create-next-app/edit/master/lib/templates/default/README.md)
235 |
--------------------------------------------------------------------------------
/template/next-template/components/head.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import NextHead from 'next/head'
3 | import { string } from 'prop-types'
4 |
5 | const defaultDescription = ''
6 | const defaultOGURL = ''
7 | const defaultOGImage = ''
8 |
9 | const Head = props => (
10 |
11 |
12 | {props.title || ''}
13 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | )
36 |
37 | Head.propTypes = {
38 | title: string,
39 | description: string,
40 | url: string,
41 | ogImage: string
42 | }
43 |
44 | export default Head
45 |
--------------------------------------------------------------------------------
/template/next-template/components/nav.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Link from 'next/link'
3 |
4 | const links = [
5 | { href: 'https://github.com/segmentio/create-next-app', label: 'Github' }
6 | ].map(link => {
7 | link.key = `nav-link-${link.href}-${link.label}`
8 | return link
9 | })
10 |
11 | const Nav = () => (
12 |
13 |
14 |
15 |
16 | Home
17 |
18 |
19 |
20 | {links.map(({ key, href, label }) => (
21 |
22 |
23 | {label}
24 |
25 |
26 | ))}
27 |
28 |
29 |
30 |
56 |
57 | )
58 |
59 | export default Nav
60 |
--------------------------------------------------------------------------------
/template/next-template/next.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | webpack: config => {
3 | // Fixes npm packages that depend on `fs` module
4 | config.node = {
5 | fs: 'empty'
6 | }
7 |
8 | return config
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/template/next-template/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "create-next-example-app",
3 | "scripts": {
4 | "dev": "next",
5 | "build": "next build",
6 | "start": "next start"
7 | },
8 | "dependencies": {
9 | "next": "^9.3.5",
10 | "react": "^16.13.1",
11 | "react-dom": "^16.13.1"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/template/next-template/pages/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import Link from 'next/link'
3 | import Head from '../components/head'
4 | import Nav from '../components/nav'
5 |
6 | const Home = () => (
7 |
8 |
9 |
10 |
11 |
12 |
Welcome to Next!
13 |
14 | To get started, edit pages/index.js
and save to reload.
15 |
16 |
17 |
40 |
41 |
42 |
88 |
89 | )
90 |
91 | export default Home
92 |
--------------------------------------------------------------------------------
/template/next-template/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oahehc/react-vue-comparison/fc756310e517a237130073651ea8a31239389c9a/template/next-template/static/favicon.ico
--------------------------------------------------------------------------------
/template/nuxt-template/.editorconfig:
--------------------------------------------------------------------------------
1 | # editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | charset = utf-8
9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 |
12 | [*.md]
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/template/nuxt-template/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | browser: true,
5 | node: true
6 | },
7 | parserOptions: {
8 | parser: 'babel-eslint'
9 | },
10 | extends: [
11 | '@nuxtjs',
12 | 'prettier',
13 | 'prettier/vue',
14 | 'plugin:prettier/recommended',
15 | 'plugin:nuxt/recommended'
16 | ],
17 | plugins: [
18 | 'prettier'
19 | ],
20 | // add your custom rules here
21 | rules: {
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/template/nuxt-template/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | ### Node template
3 | # Logs
4 | /logs
5 | *.log
6 | npm-debug.log*
7 | yarn-debug.log*
8 | yarn-error.log*
9 |
10 | # Runtime data
11 | pids
12 | *.pid
13 | *.seed
14 | *.pid.lock
15 |
16 | # Directory for instrumented libs generated by jscoverage/JSCover
17 | lib-cov
18 |
19 | # Coverage directory used by tools like istanbul
20 | coverage
21 |
22 | # nyc test coverage
23 | .nyc_output
24 |
25 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
26 | .grunt
27 |
28 | # Bower dependency directory (https://bower.io/)
29 | bower_components
30 |
31 | # node-waf configuration
32 | .lock-wscript
33 |
34 | # Compiled binary addons (https://nodejs.org/api/addons.html)
35 | build/Release
36 |
37 | # Dependency directories
38 | node_modules/
39 | jspm_packages/
40 |
41 | # TypeScript v1 declaration files
42 | typings/
43 |
44 | # Optional npm cache directory
45 | .npm
46 |
47 | # Optional eslint cache
48 | .eslintcache
49 |
50 | # Optional REPL history
51 | .node_repl_history
52 |
53 | # Output of 'npm pack'
54 | *.tgz
55 |
56 | # Yarn Integrity file
57 | .yarn-integrity
58 |
59 | # dotenv environment variables file
60 | .env
61 |
62 | # parcel-bundler cache (https://parceljs.org/)
63 | .cache
64 |
65 | # next.js build output
66 | .next
67 |
68 | # nuxt.js build output
69 | .nuxt
70 |
71 | # Nuxt generate
72 | dist
73 |
74 | # vuepress build output
75 | .vuepress/dist
76 |
77 | # Serverless directories
78 | .serverless
79 |
80 | # IDE / Editor
81 | .idea
82 |
83 | # Service worker
84 | sw.*
85 |
86 | # macOS
87 | .DS_Store
88 |
89 | # Vim swap files
90 | *.swp
91 |
--------------------------------------------------------------------------------
/template/nuxt-template/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "semi": false,
3 | "arrowParens": "always",
4 | "singleQuote": true
5 | }
6 |
--------------------------------------------------------------------------------
/template/nuxt-template/README.md:
--------------------------------------------------------------------------------
1 | # nuxt-template
2 |
3 | > My glorious Nuxt.js project
4 |
5 | ## Build Setup
6 |
7 | ```bash
8 | # install dependencies
9 | $ yarn install
10 |
11 | # serve with hot reload at localhost:3000
12 | $ yarn dev
13 |
14 | # build for production and launch server
15 | $ yarn build
16 | $ yarn start
17 |
18 | # generate static project
19 | $ yarn generate
20 | ```
21 |
22 | For detailed explanation on how things work, check out [Nuxt.js docs](https://nuxtjs.org).
23 |
--------------------------------------------------------------------------------
/template/nuxt-template/assets/README.md:
--------------------------------------------------------------------------------
1 | # ASSETS
2 |
3 | **This directory is not required, you can delete it if you don't want to use it.**
4 |
5 | This directory contains your un-compiled assets such as LESS, SASS, or JavaScript.
6 |
7 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#webpacked).
8 |
--------------------------------------------------------------------------------
/template/nuxt-template/components/Logo.vue:
--------------------------------------------------------------------------------
1 |