The skill is in the toss. React+ TS type inference improves development efficiency. And now Vue3. X supports TS, but Vue3. If Vue2. X also supports TS, it will improve our development efficiency. However, Vue2- CLI Webpack3.x presents various errors in Typescript compilation, and Webpack4.x has greatly improved packaging speed and efficiency, so we decided to upgrade Webpack and use the latest Webpack4.x to support Typescript. No more nonsense, on the configuration:
Create a Vue project
$NPM install -g vue-cli # create a new project based on webpack template $vue init webpack vue-ts-project $CD vue-ts-project # $NPM run dev = $NPM run dev = $NPM run devCopy the code
Start by upgrading Webpack to 4.x
Upgrade the NPM package in package.json
webpack
"webpack": "^ 3.6.0"= >"^ 4.29.6"
"webpack-bundle-analyzer": "^ 2.9.0"= >"^ 3.1.0"
"webpack-cli": "^ 3.3.0" (ADD)
"webpack-dev-server": "^ 2.9.1." "= >"^ 3.1.11"
"webpack-merge": "^ 4.1.0." "= >"^ 2"
Copy the code
loader
"css-loader": "^ 0.28.0"= >"^ 2.1.1"
"file-loader": "^ 1.1.4." "= >"^ 3.0.1." "
"inject-loader": "^ 3.0.0"= >"^ 4.0.1." "
"postcss-loader": "^ mid-atlantic moved." "= >"^ 3.0.0"
"url-loader": "^ 0.5.8"= >"^ 1.1.2." "
"vue-loader": "^ 13.3.0"= >"^ 15.7.0"
"vue-style-loader": "^ 3.0.1." "= >"^ 4.1.2." "
"vue-template-compiler": "^ 2.5.2." "= >"^ 2.6.9." "
Copy the code
plugin
"copy-webpack-plugin": "^ 4.0.1." "= >"^ 5.0.1." "
"friendly-errors-webpack-plugin": "^ 1.6.1." "= >"^ 1.7.0"
"html-webpack-plugin": "^ 2.30.1"= >"^ 3.2.0"
"optimize-css-assets-webpack-plugin": "^ 3.2.0"= >"^ 5.0.1." "
"extract-text-webpack-plugin": "^ 3.0.0" (DEL)
"mini-css-extract-plugin": "^ 0.5.0" (ADD)
Copy the code
eslint
"eslint": "^ 4.15.0"= >"^ 4.19.1"
"eslint-config-standard": "^ 10.2.1"= >"^ 11.0.0"
"eslint-friendly-formatter": "^ 3.0.0"= >"^ 4.0.1." "
"eslint-loader": "^ 1.7.1." "= >"^ 2.0.0." "
"eslint-plugin-import": "^ 2.7.0"= >"^ 2.12.0"
"eslint-plugin-node": "^ 5.2.0." "= >"^ the 6.0.1." "
"eslint-plugin-promise": "^ 3.4.0"= >"^ 3.7.0"
"eslint-plugin-standard": "^ 3.0.1." "= >"^ 3.1.0"
"eslint-plugin-vue": "^ 4.0.0"= >"^ 4.5.0." "
Copy the code
Configuration changes
build/webpack.base.conf.js
+ const { VueLoaderPlugin } = require('vue-loader')
module.exports = {
+ plugins: [
+ new VueLoaderPlugin()
+ ],
resolve: {
extensions: ['.js'.'.ts'.'.vue'.'.json'].alias: {
'vue$': 'vue/dist/vue.esm.js'.The '@': resolve('src'),}}}Copy the code
build/webpack.prod.conf.js
- // const ExtractTextPlugin = require('extract-text-webpack-plugin')
- // const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
+ const MiniCssExtractPlugin = require('mini-css-extract-plugin')
+ const { VueLoaderPlugin } = require('vue-loader')
const webpackConfig = merge(baseWebpackConfig, {
+ optimization: {
+ minimize: true,
+ 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'+}},plugins: [+new MiniCssExtractPlugin({
+ filename: utils.assetsPath('css/[name].[contenthash].css'),
+ allChunks: true, - +})// new ExtractTextPlugin({
- // filename: utils.assetsPath('css/[name].[contenthash].css'),
- // allChunks: true,
- // }),
- // new UglifyJsPlugin({
- // uglifyOptions: {
- // compress: {
- // warnings: false
- / /}
- / /},
- // sourceMap: config.build.productionSourceMap,
- // parallel: true
- // }),
- // new webpack.optimize.CommonsChunkPlugin({
- // name: 'vendor',
- // minChunks (module) {
- // return (
- // module.resource && /\.js$/.test(module.resource) &&
- // module.resource.indexOf(
- // path.join(__dirname, '.. /node_modules')
- / /) = = = 0
- / /)
- // }
- // }),
- // new webpack.optimize.CommonsChunkPlugin({
- // name: 'manifest',
- // minChunks: Infinity
- // }),
- // new webpack.optimize.CommonsChunkPlugin({
- // name: 'app',
- // async: 'vendor-async',
- // children: true,
- // minChunks: 3
- // }),]}Copy the code
build/utils.js
- // const ExtractTextPlugin = require('extract-text-webpack-plugin')
+ const MiniCssExtractPlugin = require('mini-css-extract-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)
- // }
+ return [
+ options.extract ? MiniCssExtractPlugin.loader : 'vue-style-loader',
+ ].concat(loaders)
}
Copy the code
Add Typescript support
Install the NPM package
$ npm install typescript ts-loader --save-dev
$ npm install vue-class-component vue-property-decorator --save-dev
Copy the code
Create the vue-shim.d.ts file under SRC
declare module "*.vue" {
import Vue from "vue"
export default Vue
}
Copy the code
Create a new tsconfig.json file in the project root directory
{
"compilerOptions": {
"allowSyntheticDefaultImports": true."experimentalDecorators": true."allowJs": true."module": "esnext"."target": "es5"."moduleResolution": "node"."isolatedModules": true."lib": [
"dom"."es5"."es6"."es7"."es2015.promise"."scripthost"]."sourceMap": true."pretty": true."strictFunctionTypes": false."importHelpers": true
},
"include": [
"src/**/*"]."exclude": [
"node_modules"]}Copy the code
Change the main.js extension to main.ts
+ import App from './App.vue'
Copy the code
Modify the webpack.base.conf.js configuration
entry: {
- app: './src/main.js'
+ app: './src/main.ts'
},
resolve: {
+ extensions: ['.js'.'.vue'.'.json'.'.ts'].alias: {
'vue$': 'vue/dist/vue.esm.js'.The '@': resolve('src'),}},module: {
rules: [
// ...
{
test: /\.tsx? $/,
loader: 'ts-loader'.exclude: /node_modules/,
options: {
appendTsSuffixTo: [/\.vue$/],},include: [resolve('src')]}// ...]},Copy the code
Modify vUE components
<template>
<div>{{msg}}</div>
</template>
<script lang="ts">
import Vue from 'vue'
import { Component } from 'vue-property-decorator'
import HelloWorld from '@/components/HelloWorld.vue'
@Component({
components: {
HelloWorld
}
})
export default class App extends Vue {
msg = 'hello world'
}
</script>
Copy the code
happy hacking
Complete code reference documentation