Skip to content

Commit 71d0ada

Browse files
Initial commit
0 parents  commit 71d0ada

23 files changed

+1131
-0
lines changed

.gitignore

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# OS generated files #
2+
.DS_Store*
3+
ehthumbs.db
4+
Icon?
5+
Thumbs.db
6+
7+
# Vuejs build result and test
8+
dist/
9+
10+
# Editor Files #
11+
*~
12+
*.swp
13+
.editorconfig
14+
.vs/
15+
.vscode/
16+
17+
# Logs
18+
logs
19+
*.log
20+
npm-debug.log*
21+
22+
# Runtime data
23+
pids
24+
*.pid
25+
*.seed
26+
*.pid.lock
27+
28+
29+
# Dependency directories
30+
node_modules
31+
jspm_packages
32+
33+
# Optional npm cache directory
34+
.npm

README.md

+318
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,318 @@
1+
# typescript-vue-example
2+
3+
> A TypeScript Vue Project Example
4+
5+
Base on the the [Jayway's Vue.js 2.0 workshop](https://jayway.github.io/vue-js-workshop/), this document describes the steps to scaffold a TypeScript Vue project and add more components to create a structure for non-trivial projects.
6+
7+
Build Setup
8+
9+
``` bash
10+
# install dependencies
11+
npm install
12+
13+
# serve with hot reload at localhost:8080
14+
npm run dev
15+
16+
# build for production with minification
17+
npm run build
18+
```
19+
20+
The following are step-by-step instructions to create the project from scracth.
21+
22+
## 1. Scaffold a Project
23+
Run `npm install -g vue-cli` to install vue-client. If you already have it, run `npm update -g vue-cli` to update it to the latest version. You may need to use `sudo` to install it as a global package.
24+
25+
### 1.1. Initialize a Vue Project
26+
27+
Run `vue init webpack typescript-vue-example` to create a new project named `typescript-vue-example`. To make it simple, don't setup ESLint, unit test and e2e tests.
28+
29+
Run the following commandto see it is up and running at http://localhost:8080/, type `ctrl-C` to exit.
30+
31+
```sh
32+
cd typescript-vue-example
33+
npm install
34+
npm run dev
35+
```
36+
37+
### 1.2. Use TypeScript Instead of Babel
38+
We use TypeScript go generate all JavaScript ES5 code, therefore there is no need to to use Bable in this project. In `package.json`, remove all lines having a "babel" prefix.
39+
40+
Then install `typescript` and `ts-loader` packages. `ts-loader` works with `vue-loader` (installed by `vue-cli` in project intialization) to process TypeScript code in a `vue` file.
41+
42+
```sh
43+
npm i -D typescript
44+
npm i -D ts-loader
45+
```
46+
47+
### 1.3. Config Webpack Loaders
48+
To use the `typescript` and `ts-loader`, we need to configure both TypeScript and Webpack.
49+
50+
### 1.3.1. Config TypeScript
51+
Create a `tsconfig.json` file in the project root folder with the following contents:
52+
53+
```json
54+
{
55+
"compilerOptions": {
56+
"target": "es5",
57+
"lib": ["es5", "es2015.promise", "dom"]
58+
}
59+
}
60+
```
61+
62+
In the above file, we set the generate JavaScript code in `es5` syntax. We also need the `es5` and `es2015.promise` libs to compile TypeScript code.
63+
64+
### 1.3.2. Config Webpack
65+
Edit `build/webpack.base.conf.js` to have the following changes:
66+
67+
```js
68+
// 1. change the entry to a .ts file
69+
entry: {
70+
app: './src/main.ts'
71+
},
72+
73+
// 2. add resolve extensions for '.ts'
74+
resolve: {
75+
extensions: ['', '.js', '.vue', '.ts'],
76+
// ...
77+
}
78+
79+
// 3. in "module: { loaders: []", replace the "bable loader for js test" to "ts-loader for ts test"
80+
{
81+
test: /\.ts$/,
82+
loader: 'ts',
83+
include: projectRoot,
84+
exclude: /node_modules/
85+
},
86+
87+
// 4. in "vue: {", set esModule to true,
88+
vue: {
89+
loaders: utils.cssLoaders({ sourceMap: useCssSourceMap }),
90+
// typescript needs it
91+
esModule: true,
92+
93+
// ...
94+
},
95+
96+
// 5. append a ".ts" file to all ".vue" file thus typescript can preprocess the file
97+
ts: {
98+
appendTsSuffixTo: [/\.vue$/]
99+
}
100+
```
101+
102+
## 2. Convert JavaScript Code to TypeScript
103+
The good news is that Vue npm package comes with type definitions and we can have type checking and editing help. However, the import syntax is different in TypeScript.
104+
105+
First, Change the `<script>` tag in `src/App.vue` and `src/components/Hello.vue` as `<script lang="ts">` for the `ts-loader` to work.
106+
107+
Then rename the entry file `src/main.js` as `src/main.ts` and edit it to have the following content:
108+
109+
```ts
110+
import * as Vue from 'vue'
111+
import App from './App'
112+
113+
/* eslint-disable no-new */
114+
new Vue({
115+
el: '#app',
116+
render: h => h(App)
117+
})
118+
```
119+
120+
To verify the changes, run the project with command `npm run dev`. You should see a page served on `http://localhost:8080/` if we make the right changes.
121+
122+
## 3. Create a Product List Component
123+
Delete the `src/components/Hello.vue` file and create a `src/components/ProductList.vue` file with the following content:
124+
125+
```html
126+
<template>
127+
<table class="table table-hover">
128+
<thead>
129+
<tr>
130+
<th>Product Id</th>
131+
<th>Name</th>
132+
<th>Description</th>
133+
<th>Price</th>
134+
</tr>
135+
</thead>
136+
<tbody>
137+
<tr v-for="product in products" track-by="id">
138+
<td>{{product.id}}</td>
139+
<td>{{product.name}}</td>
140+
<td>{{product.description}}</td>
141+
<td>{{product.price}}</td>
142+
</tr>
143+
</tbody>
144+
</table>
145+
</template>
146+
147+
<script lang="ts">
148+
export default {}
149+
</script>
150+
```
151+
152+
In the above `ProductList.vue` file, though we don't have anything for for the `<script>` section, for TypeScript to work, we let it export an empty object.
153+
154+
Then change the `App.vue` as the following to use the new product list component.
155+
156+
```ts
157+
<template>
158+
<product-list></product-list>
159+
</template>
160+
161+
<script lang="ts">
162+
import ProductList from './components/ProductList'
163+
164+
export default {
165+
name: 'app',
166+
components: {
167+
ProductList
168+
}
169+
}
170+
</script>
171+
```
172+
173+
Run `npm run dev` to check that the site is up and running correctly.
174+
175+
## 4. Use BootStrap 4 Styles
176+
We use BootStrap 4 alpha to style the page. We may see the final release in our life time.
177+
178+
### 4.1. Install BootStrap 4
179+
Run `npm i -S [email protected]` to install BootStrap 4.
180+
181+
### 4.2. Install `node-saas` and `sass-loader`
182+
Run the following two commands to install `node-sass` and `sass-loader`.
183+
```sh
184+
npm i -D node-sass
185+
npm i -D sass-loader
186+
```
187+
188+
### 4.3. Create a Style File with Standard Style
189+
create a `src/styles` folder and create a `style.scss` file with the following content:
190+
191+
```
192+
@import "../../node_modules/bootstrap/scss/bootstrap-flex.scss";
193+
```
194+
195+
### 4.4. Use the Created Style
196+
Import the standard bootstrap style by adding the following contents to `main.js`.
197+
198+
```js
199+
// import some global styles
200+
import './styles/style.scss'
201+
```
202+
203+
Run `npm run dev` to check that the site is up and running correctly.
204+
205+
## 5. Create a State Store
206+
To make the project scalable, We use modules to manage the store for different parts of an application. In the `src/store` folder, we define types for all store modules. Each module has a type file.
207+
208+
### 5.1. Install `vuex`
209+
Run `npm i -S vuex` to install the Vue state store plugin.
210+
211+
### 5.3. Create Type Constants
212+
Create `src/store/products-types.ts` file as the following:
213+
214+
```js
215+
export const GET_PRODUCTS = 'products/GET_PRODUCTS'
216+
```
217+
218+
The reason that we create this file is that there will be a types file for each store module.
219+
220+
## 5.3. Create the `getProducts` Getter
221+
Create `src/store/modules/products/getters.ts` as the following:
222+
223+
```ts
224+
import { GET_PRODUCTS } from '../../products-types'
225+
226+
export const getters = {
227+
[GET_PRODUCTS] (state) {
228+
return state.products
229+
}
230+
}
231+
```
232+
233+
For a non-trivial project, there will be getters, mutations, and actions and each type will be in one or more file.
234+
235+
### 5.4 Create the Products Store Module
236+
Create `src/store/modules/products/index.ts` with the following content:
237+
238+
```ts
239+
import { getters } from './getters'
240+
241+
const initialState = {
242+
products: [
243+
{
244+
id: '001',
245+
name: 'COBOL 101 vintage',
246+
description: 'Learn COBOL with this vintage programming book',
247+
price: 399,
248+
},
249+
{
250+
id: '007',
251+
name: 'Sharp C2719 curved TV',
252+
description: 'Watch TV like with new screen technology',
253+
price: 1995,
254+
},
255+
{
256+
id: '719',
257+
name: 'Remmington X mechanical keyboard',
258+
description: 'Excellent for gaming and typing',
259+
price: 595,
260+
}
261+
]
262+
}
263+
264+
export default {
265+
state: {
266+
...initialState
267+
},
268+
getters
269+
}
270+
```
271+
272+
This is the module-levle store file that exposes all module states and methods.
273+
274+
### 5.5. Add the Store to the Root Instance
275+
In `src/main.ts`, import the newly created store and add it to the root instance option. After this, all child components can access the store.
276+
277+
```ts
278+
declare let process: any
279+
280+
import * as Vue from 'vue'
281+
import * as Vuex from 'vuex'
282+
283+
import products from './modules/products'
284+
285+
Vue.use(Vuex)
286+
287+
const debug = process.env.NODE_ENV !== 'production'
288+
289+
export default new Vuex.Store({
290+
modules: {
291+
products
292+
},
293+
strict: debug
294+
})
295+
```
296+
297+
This is the root-level store file that exposes all store modules.
298+
299+
### 5.6. Use the Store in ProductList Component
300+
to get products data from the store using a computed property, change the content of `<script lang="ts"> </script>` of the `src/components/ProductList.vue` fiel as the following:
301+
302+
```ts
303+
<script lang="ts">
304+
import * as Vuex from 'vuex'
305+
306+
import * as types from '../store/products-types'
307+
308+
export default {
309+
computed: Vuex.mapGetters({
310+
products: types.GET_PRODUCTS
311+
})
312+
}
313+
</script>
314+
```
315+
316+
In the above code, we map the `types.GET_PRODUCTS` getter meethod to a local computed property with a name `products`.
317+
318+
Run `npm run dev` to check that the site is up and running correctly.

build/build.js

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// https://github.com/shelljs/shelljs
2+
require('./check-versions')()
3+
require('shelljs/global')
4+
env.NODE_ENV = 'production'
5+
6+
var path = require('path')
7+
var config = require('../config')
8+
var ora = require('ora')
9+
var webpack = require('webpack')
10+
var webpackConfig = require('./webpack.prod.conf')
11+
12+
console.log(
13+
' Tip:\n' +
14+
' Built files are meant to be served over an HTTP server.\n' +
15+
' Opening index.html over file:// won\'t work.\n'
16+
)
17+
18+
var spinner = ora('building for production...')
19+
spinner.start()
20+
21+
var assetsPath = path.join(config.build.assetsRoot, config.build.assetsSubDirectory)
22+
rm('-rf', assetsPath)
23+
mkdir('-p', assetsPath)
24+
cp('-R', 'static/*', assetsPath)
25+
26+
webpack(webpackConfig, function (err, stats) {
27+
spinner.stop()
28+
if (err) throw err
29+
process.stdout.write(stats.toString({
30+
colors: true,
31+
modules: false,
32+
children: false,
33+
chunks: false,
34+
chunkModules: false
35+
}) + '\n')
36+
})

0 commit comments

Comments
 (0)