Vue+webpackDevMiddleware+TypeScript

2019-08-15 admin

Vue + webpack-dev-middleware + TypeScript

一、背景

基础项目

基础项目是基于vue-cli+webpack-dev-middleware的项目。首先前端使用vue-cli搭建的环境(本教程略),然后使用express,配合webpack-dev-middleware发布前端文件。 server.js文件如下:

const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const config = require('./config/index')

const app = express();
const webpackConfig = require('./build/webpack.server.conf.js');
const compiler = webpack(webpackConfig);

// Tell express to use the webpack-dev-middleware and use the webpack.config.js
// configuration file as a base.
app.use(webpackDevMiddleware(compiler, {
  publicPath: webpackConfig.output.publicPath
}));

// Serve the files on port 3000.
const PORT = config.dev.port
app.listen(PORT, function () {
  console.log('Example app listening on port ' + PORT + '!\n');
});

Github项目:Vue-webpackDevMiddleware

webpack-dev-middleware

An express-style development middleware for use with webpack bundles and allows for serving of the files emitted from webpack. This should be used for development only.

仅用于开发环境,通常与Express配合使用,通过webpack工具可以对前端文件进行打包,配合webpack-hot-middleware可实现热加载。 Github项目:webpack-dev-middleware

二、开始改造

安装一些依赖 为了支持TypeScript,需要增加一些依赖:

  • style-loader 1.0.0
  • ts-loader 6.0.4
  • tslint 5.18.0
  • tslint-config-standard 8.0.1
  • tslint-loader 3.5.4
  • typescript 3.2.2
  • vue-class-component 7.1.0
  • vue-property-decorator 8.1.1

注意,安装这些依赖要指定版本,不然不同版本的插件可能会不兼容。在package.json中,也把依赖的版本^去掉,防止不兼容。 除了新增了一些依赖,同时某些依赖的版本也有变化,建议直接拷贝下面的package.json文件,然后npm install安装。

{
  "name": "Vue-webpackDevMiddleware",
  "version": "1.0.0",
  "description": "A Vue project based on express. Use Webpack-dev-middleware to build a dev enviroment.",
  "author": "David-Shi-1989 <287841605@qq.com>",
  "private": true,
  "scripts": {
    "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
    "start": "webpack-dev-server --open",
    "server": "node server.js",
    "unit": "jest --config test/unit/jest.conf.js --coverage",
    "e2e": "node test/e2e/runner.js",
    "test": "npm run unit && npm run e2e",
    "lint": "eslint --ext .js,.vue src test/unit test/e2e/specs",
    "build": "node build/build.js"
  },
  "dependencies": {
    "vue": "2.5.16",
    "vue-router": "3.0.1"
  },
  "devDependencies": {
    "autoprefixer": "7.2.6",
    "babel-core": "6.26.3",
    "babel-eslint": "8.2.3",
    "babel-helper-vue-jsx-merge-props": "2.0.3",
    "babel-jest": "21.2.0",
    "babel-loader": "7.1.4",
    "babel-plugin-dynamic-import-node": "1.2.0",
    "babel-plugin-syntax-jsx": "6.18.0",
    "babel-plugin-transform-es2015-modules-commonjs": "6.26.2",
    "babel-plugin-transform-runtime": "6.23.0",
    "babel-plugin-transform-vue-jsx": "3.7.0",
    "babel-preset-env": "1.6.1",
    "babel-preset-stage-2": "6.24.1",
    "babel-register": "6.26.0",
    "chalk": "2.4.1",
    "clean-webpack-plugin": "0.1.19",
    "copy-webpack-plugin": "4.5.1",
    "cross-spawn": "5.1.0",
    "css-loader": "0.28.11",
    "eslint": "4.19.1",
    "eslint-config-standard": "10.2.1",
    "eslint-friendly-formatter": "3.0.0",
    "eslint-loader": "2.1.0",
    "eslint-plugin-import": "2.11.0",
    "eslint-plugin-node": "5.2.1",
    "eslint-plugin-promise": "3.7.0",
    "eslint-plugin-standard": "3.1.0",
    "eslint-plugin-vue": "4.5.0",
    "express": "4.16.3",
    "extract-text-webpack-plugin": "4.0.0-beta.0",
    "file-loader": "1.1.11",
    "font-awesome": "4.7.0",
    "friendly-errors-webpack-plugin": "1.7.0",
    "html-webpack-plugin": "3.2.0",
    "jest": "22.4.3",
    "jest-serializer-vue": "0.3.0",
    "nightwatch": "0.9.21",
    "node-notifier": "5.2.1",
    "optimize-css-assets-webpack-plugin": "3.2.0",
    "ora": "1.4.0",
    "portfinder": "1.0.13",
    "postcss-import": "11.1.0",
    "postcss-loader": "2.1.4",
    "postcss-url": "7.3.2",
    "rimraf": "2.6.2",
    "selenium-server": "3.11.0",
    "semver": "5.5.0",
    "shelljs": "0.7.8",
    "style-loader": "1.0.0",
    "ts-loader": "6.0.4",
    "tslint": "5.18.0",
    "tslint-config-standard": "8.0.1",
    "tslint-loader": "3.5.4",
    "typescript": "3.2.2",
    "uglifyjs-webpack-plugin": "1.2.5",
    "url-loader": "0.5.9",
    "vue-class-component": "7.1.0",
    "vue-jest": "1.4.0",
    "vue-loader": "14.2.2",
    "vue-property-decorator": "8.1.1",
    "vue-style-loader": "3.1.2",
    "vue-template-compiler": "2.5.16",
    "webpack": "4.0.0",
    "webpack-bundle-analyzer": "2.11.1",
    "webpack-cli": "2.1.2",
    "webpack-dev-middleware": "2.0.6",
    "webpack-dev-server": "3.1.0",
    "webpack-merge": "4.1.2"
  },
  "engines": {
    "node": ">= 6.0.0",
    "npm": ">= 3.0.0"
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not ie <= 8"
  ]
}

修改webpack配置文件 与vue-cli搭出来的纯前端不同,我们这里使用express发布,webpack配置文件在build\webpack.server.conf.js。需要修改以下几点:

1.entry入口文件 入口文件由main.js改为main.ts

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

同时把src\main.js重命名为main.ts,文件内容如下:

// The Vue build version to load with the import command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from '@/App.vue'
import router from '@/router/index'

Vue.config.productionTip = false

/* eslint-disable no-new */
new Vue({
  router,
  render: (h) => h(App)
}).$mount('#app')

2.resolve.extensions增加ts

resolve: {
  extensions: ['.ts', '.js', '.vue', '.json'],
  alias: {
    'vue/div>: 'vue/dist/vue.esm.js',
    '@': resolve('./src'),
  }
}

3.module.rules增加ts的规则

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

4.新建文件tsconfig.json

{
  "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
  }
}

5.新建文件src\vue-shims.d.ts

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

6.新建文件tslint.json

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

此时到这里,运行server.js(node server.js),页面可以正常打开。

修改vue文件 此时项目已经支持ts了,接下来修改vue文件,将js代码改为ts代码。

  • 修改App.vue 由于实现等原因,ts代码放进vue文件不生效,所以把ts代码提出来,放在单独的ts文件里,在vue文件中引入。 App.vue:

    <template>
      <div id="app">
        <img src="./assets/logo.png">
        <router-view/>
      </div>
    </template>
    
    <script lang="ts" src="./App.ts"></script>
    
    <style>
    #app {
      font-family: 'Avenir', Helvetica, Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      text-align: center;
      color: #2c3e50;
      margin-top: 60px;
    }
    </style>
    
    

    App.ts:

    import Vue from 'vue'
    import { Component } from 'vue-property-decorator'
    
    @Component({
    })
    export default class App extends Vue{
      created () {
        console.log(`App created`)
      }
    }
    
  • 新增组件person-info.vue person-info.vue:

    <template>
      <p>
        <span>{{name}}</span>
        <span>{{age}}</span>
        <span>{{nickName}}</span>
        <span>{{timestamp}}</span>
      </p>
    </template>
    
    <script lang="ts" src="./person-info.ts">
    </script>
    <style scoped>
    </style>
    
    

    person-info.ts:

    import { Vue, Component, Prop } from 'vue-property-decorator'
    
    @Component({})
    export default class HelloWorld extends Vue {
      @Prop(String) name: string | undefined
      @Prop(Number) age: number | undefined
      @Prop(String) nickName: string | undefined
      @Prop(String) timestamp: string
    }
    
    
  • 修改HelloWorld.vue HelloWorld.vue引入person-info组件:


<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
    <h2>Essential Links</h2>
    <ul>
      <li>
        <a
          href="https://vuejs.org"
          target="_blank"
        >
          Core Docs
        </a>
      </li>
      <li>
        <a
          href="https://forum.vuejs.org"
          target="_blank"
        >
          Forum
        </a>
      </li>
      <li>
        <a
          href="https://chat.vuejs.org"
          target="_blank"
        >
          Community Chat
        </a>
      </li>
      <li>
        <a
          href="https://twitter.com/vuejs"
          target="_blank"
        >
          Twitter
        </a>
      </li>
      <br>
      <li>
        <a
          href="http://vuejs-templates.github.io/webpack/"
          target="_blank"
        >
          Docs for This Template
        </a>
      </li>
    </ul>
    <h2>Ecosystem</h2>
    <ul>
      <li>
        <a
          href="http://router.vuejs.org/"
          target="_blank"
        >
          vue-router
        </a>
      </li>
      <li>
        <a
          href="http://vuex.vuejs.org/"
          target="_blank"
        >
          vuex
        </a>
      </li>
      <li>
        <a
          href="http://vue-loader.vuejs.org/"
          target="_blank"
        >
          vue-loader
        </a>
      </li>
      <li>
        <a
          href="https://github.com/vuejs/awesome-vue"
          target="_blank"
        >
          awesome-vue
        </a>
      </li>
    </ul>
    <personInfo :name="name" :age="age" nickName="sdas" :timestamp="ts"></personInfo>
  </div>
</template>

<script lang="ts" src="./HelloWorld.ts"></script>

<style scoped>
h1, h2 {
  font-weight: normal;
}
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #42b983;
}
</style>

HelloWorld.ts文件:


import { Vue, Component } from 'vue-property-decorator'
import personInfo from './person-info.vue'

@Component({
  components: {
    personInfo
  }
})
export default class HelloWorld extends Vue {
  msg: string = 'Welcome Typescript + Vue'
  ts: string = ''
  name: string = 'david'
  age: number = 29
  created () {
    this.ts = String(Date.now().valueOf())
    console.log(this.ts)
  }
}

三、结束

运行效果

此时,运行出来的页面如下: 最终效果

总结

改进

  • 解决告警mode WARNING in configuration. The ‘mode’ option has not been set. Set ‘mode’ option to ‘development’ or ‘production’ to enable defaults for this environment. 解决办法:在build\webpack.server.conf.js中增加mode如下:

    // ...
    module.exports = {
      entry: {
        app: './src/main.ts'
      },
      mode: 'development',
      // ...
    
  • 告警 Warning: The ‘await-promise’ rule requires type information.等告警 解决办法: 待解决

  • ts代码写入vue文件中 解决办法: 待解决

[转载]原文链接:https://segmentfault.com/a/1190000020078102

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-72563.html

文章标题:Vue+webpackDevMiddleware+TypeScript

相关文章
vue-awesome-swiper的使用以及API整理
一、先说一个看关于vue-awesome-swiper的一个坑 vue项目的package.json中显示的&lt;span style=“color: orange;”&gt;“vue-awesome-swiper”: “^2.5.4”&...
2018-04-26
vuejs通过filterBy、orderBy实现搜索筛选、降序排序数据
直接贴代码了: 先上输入前的样子: &lt;style&gt; #example{margin:100px auto;width:600px;} .show{margin:10px;} #searchText{display: block...
2017-03-17
最细致的vue.js基础语法 值得收藏!
介绍 前段时间接触到一个库叫做Vue.js, 个人感觉很棒,所以整理了一篇博文做个介绍。 Vue读音/vju:/,和view类似。是一个数据驱动的web界面库。Vue.js只聚焦于视图层,可以很容易的和其他库整合。代码压缩后只有24kb。 ...
2017-03-21
mpvue 小程序如何开启下拉刷新,上拉加载?
https://developers.weixin.qq.com/miniprogram/dev/api/pulldown.html#onpulldownrefresh 小程序API 微信小程序之下拉加载和上拉刷新 微信小程序下拉加载和上拉...
2018-05-25
mpvue 小程序如何自定义tabBar,不使用navigateTo跳转,模拟redirectTo跳转
原生tabBar tabBar: { &quot;list&quot;: [ { pagePath: &quot;pages&#x2F;index&#x2F;main&quot;, iconPath: &...
2018-05-25
vue使用watch 观察路由变化,重新获取内容
问题背景: 点击用户头像 =&gt; 进入用户个人中心,在用户个人中心里点击其他用户的头像,我希望显示被点击用户的个人中心,但只看到了路由参数在发生变化,页面内容并没有更新。如图: 页面代码如下: &lt;script&gt; exp...
2017-03-13
在 mpvue 使用 echarts 小程序组件
具体操作 下载 echarts-for-weixin 。 把其 ec-canvas 目录移动到 mpvue 项目的 static 目录下。 对 ec-canvas/ec-canvas.js 进行小调整,考虑提 pr 到 ec-c...
2018-03-11
VuePress 快速踩坑
最近有个开源项目非常火,那就是尤小右开发的 VuePress,VuePress 可以让您非常方便的在 Markdown 文档中编写 Vue 代码,并且 VuePress 对编译后的 HTML 文件做了一些针对搜索引擎的优化。另外 VuePr...
2018-04-27
vue-video-player 更改视频源
背景:根据用户的信息来显示不同的视频源 &lt;template&gt; &lt;div class=&quot;video-box-wrap&quot; v-show=&quot;video.show&quot;&gt; ...
2018-05-05
Vue 短信验证码组件开发详解
Vue.js(读音 /vjuː/, 类似于 view)是一个构建数据驱动的 web 界面的库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。 Vue.js 自身不是一个全能框架——它只聚焦于视图层。因此...
2017-03-17
回到顶部