vue+webpack4+TypeScript

本文介紹瞭如何從0開始搭建一個vue+webpack4+typescript項目

github地址:https://github.com/seanffy/vue-webpack4-TypeScript

1、創建項目

使用vue init webpack project創建一個vue+webpack3+js的項目。
Pasted Graphic 2.tiff

2、安裝插件

將webpack、webpack-dev-server升級到最新版本,其次安裝webpack-cli更新最新版本使用。
npm install webpack@latest —save-dev
Pasted Graphic 3.tiff

3、配置開發環境

npm install加載依賴包,運行npm run dev會報錯
Pasted Graphic 4.tiff
此時我們需要更新html-webpack-plugin。再次運行會報eslint錯誤,關閉eslint規則,在webpack.base.conf.js把createLintingRule()去掉即可
Pasted Graphic 5.tiff
重新運行
Pasted Graphic 6.tiff
需要升級vue-loader,使用npm install vue-loader@latest —save-dev
升級完成之後再webpack.base.conf.js中添加

const { VueLoaderPlugin } = require('vue-loader')
module.exports = {
    mode : 'none', // 有development跟production、none三種情況,webpack4如果不設置打包完成會報錯,如果有qa或者pl環境可以設置爲none
    ***
    plugins: [
        new VueLoaderPlugin()
    ],
    ***
}

開發環境升級完成

4、配置生產環境

首先在prod環境中添加mode:’none’或者mode:’production’
用optimization代替以前的webpack.optimize.CommonsChunkPlugin、uglifyjs-webpack-plugin、webpack.optimize.ModuleConcatenationPlugin

const webpackConfig = merge(baseWebpackConfig, {
  // ...
  mode: 'production',
  // webpack4 內置
  optimization: {
    splitChunks: {
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          chunks: 'initial',
          name: 'vendors',
        },
        'async-vendors': {
          test: /[\\/]node_modules[\\/]/,
          minChunks: 2,
          chunks: 'async',
          name: 'async-vendors'
        }
      }
    },
    runtimeChunk: { name: 'runtime' }
  },
}

重新打包,報錯
Pasted Graphic 7.tiff
extract-text-webpack-plugin插件有問題,推薦使用mini-css-extract-plugin,修改webpack.prod.conf.js和util.js配置

//webpack.prod.conf.js

// const ExtractTextPlugin = require('extract-text-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

// ...
// extract css into its own file
// new ExtractTextPlugin({
// ...
// })
// 升級 webpack4, 由 ExtractTextPlugin 改用 MiniCssExtractPlugin
new MiniCssExtractPlugin({
  filename: utils.assetsPath('css/[name].[contenthash].css'),
  allChunks: true,
}),

//util.js
// const ExtractTextPlugin = require('extract-text-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

// generate loader string to be used with extract text plugin
function generateLoaders (loader, loaderOptions) {
  const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]

  if (loader) {
    loaders.push({
      loader: loader + '-loader',
      options: Object.assign({}, loaderOptions, {
        sourceMap: options.sourceMap
      })
    })
  }

  // Extract CSS when that option is specified
  // (which is the case during production build)
  // if (options.extract) {
  //   return ExtractTextPlugin.extract({
  //     use: loaders,
  //     fallback: 'vue-style-loader'
  //   })
  // } else {
  //   return ['vue-style-loader'].concat(loaders)
  // }
  // 升級 webpack4, 由 ExtractTextPlugin 改用 MiniCssExtractPlugin
  return [
    options.extract ? MiniCssExtractPlugin.loader : 'vue-style-loader',
  ].concat(loaders)
}

打包完成,完成將webpack3升級到webpack4

5、引入ts

安裝vue的官方插件

npm i vue-class-component vue-property-decorator --save

// ts-loader typescript 必須安裝,其他的相信你以後也會裝上的
npm i ts-loader typescript tslint tslint-loader tslint-config-standard --save-dev

配置webpack
./build/webpack.base.conf.js,將entry.app中的main.js改成main.ts,順便把項目文件中的main.js改成main.ts

entry: {
  app: './src/main.ts'
}

找到resolve.extensions 裏面加上.ts 後綴 (是爲了之後引入.ts的時候不寫後綴)

resolve: {
  extensions: ['.js', '.vue', '.json', '.ts'],
  alias: {
    '@': resolve('src')
  }
}

找到module.rules 添加webpack對.ts的解析

module: {
  rules: [
    { // 添加tslint
      test: /\.ts$/,
      exclude: /node_modules/,
      enforce: 'pre',
      loader: 'tslint-loader'
    },
    { // 添加tsloader
      test: /\.tsx?$/,
      loader: 'ts-loader',
      exclude: /node_modules/,
      options: {
        appendTsSuffixTo: [/\.vue$/],
      }
    },
  ]
}

添加tsconfig.js

{
  "include": [
    "src/**/*"
  ],
  "exclude": [
    "node_modules"
  ],
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "experimentalDecorators": true,
    "allowJs": true,
    "module": "esnext",
    "target": "es5",
    "moduleResolution": "node",
    "isolatedModules": true,
    "lib": [
      "dom",
      "es5",
      "es2015.promise"
    ],
    "sourceMap": true,
    "pretty": true
  }
}

添加tslint.json

{
  "extends": "tslint-config-standard",
  "globals": {
    "require": true
  }
}

讓ts識別.vue
由於ts默認並不支持*.vue後綴的文件,所以在vue項目中引入的時候需要創建一個vue-shim.d.ts文件,擋在項目對應使用目錄下,例如

// src/vue-shim.d.ts

declare module "*.vue" {
  import Vue from "vue";
  export default Vue;
}

意思是告訴 TypeScript *.vue 後綴的文件可以交給 vue 模塊來處理。
而在代碼中導入 .vue 文件的時候,需要寫上 .vue 後綴。原因還是因爲 TypeScript 默認只識別 .ts 文件,不識別 *.vue 文件

import Component from 'components/component.vue'

改造.vue文件

<template>
  <div id="app">
    <img src="./assets/logo.png">
    <router-view/>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
import Component from 'vue-class-component'

@Component({})
export default class App extends Vue {
}
</script>

<style>

</style>

7、將router下的index.js換成index.ts

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld.vue'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    }
  ]
})

使用npm run dev 運行項目成功。
但是這裏有個問題就是當前文件是.vue文件,使用ts會有一個錯誤提示
Pasted Graphic 8.tiff
所以這裏想着把ts跟html文件分開,使用.ts後綴文件,拿App.vue舉例說明
首先創建App.html文件
Pasted Graphic 9.tiff
然後創建App.ts文件
Pasted Graphic 10.tiff
使用npm run dev會報錯
Pasted Graphic 11.tiff
提示當前沒有獲取到template的html文件
這時需要配置一個raw-loader將當前.html文件展示在template上,使用npm install raw-loader@latest —save-dev

// webpack.base.conf.js

{
    test: /\.html$/,
    loader: "raw-loader",
    exclude: [/.\/src\/index.html/],
 }

Pasted Graphic 12.tiff
配置完成npm run dev 運行項目,根據當前raw-loader版本不同可能會報錯
Pasted Graphic 13.tiff
如果報錯需要更改一下.html的require方式,更改爲

require(‘./App.html’).default

Pasted Graphic 14.tiff

至此完成vue+webpack4+typescript搭建項目

6、綁定原型方法

當我們搭建完成項目之後,可能會想在vue.prototype上綁定例如$axios等方法,這時我們使用以前的方法

import axios from ‘axios’
Vue.prototype.$axios = axios;

當我們使用this.$axios時會報錯
Pasted Graphic 1.tiff
Pasted Graphic.tiff
這時,我們需要在src目錄下創建一個vue-shim.d.ts文件,添加如下內容即可

//    在 types/vue.d.ts 裏 Vue 有構造函數類型
declare module 'vue/types/vue' {
  // 3. 聲明爲 Vue 補充的東西
  interface Vue {
    $axios: any
  }
}

Vue官網上個對此有解釋
https://cn.vuejs.org/v2/guide...
Pasted Graphic 2.tiff

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章