Webpack 如何使流与Vue 2(网页包)正常工作?
我正在尝试添加到Vue 2网页包模板。作为记录,我只在运行时(文件遵循Webpack 如何使流与Vue 2(网页包)正常工作?,webpack,vue.js,vuejs2,babeljs,flowtype,Webpack,Vue.js,Vuejs2,Babeljs,Flowtype,我正在尝试添加到Vue 2网页包模板。作为记录,我只在运行时(文件遵循.vue格式/标准) 我的第一次尝试是通过cli使用flow,我意识到它无法工作,因为它不知道如何处理.vue文件 我的第二次尝试是添加一个webpack加载程序(即)并在构建过程中运行流检查(例如,像eslintworks)。那不起作用,所以我考虑了其他的选择 我的第三次尝试是使用一个babel插件,它一开始相当成功。我用了+。Webpack中没有输出,但是类型错误会破坏应用程序。我对这种方法很满意;它可以与CI一起正常工作
.vue
格式/标准)
我的第一次尝试是通过cli使用flow,我意识到它无法工作,因为它不知道如何处理.vue
文件
我的第二次尝试是添加一个webpack加载程序(即)并在构建过程中运行流检查(例如,像eslint
works)。那不起作用,所以我考虑了其他的选择
我的第三次尝试是使用一个babel插件,它一开始相当成功。我用了+。Webpack中没有输出,但是类型错误会破坏应用程序。我对这种方法很满意;它可以与CI一起正常工作,并破坏构建
下面是我的.babelrc
的外观:
{
...
"plugins": [
...
["typecheck", {
"disable": {
"production": true
}
}],
"syntax-flow",
"transform-flow-strip-types"
],
...
}
在这一点上,流与全局方法的预期一样工作,但在Vue组件中不工作:
<template>...</template>
<script>
/* @flow */
const flowIt = (a: number): number => {
return a * 10
}
flowIt(20)
flowIt('bah') // Uncaught TypeError: Value of argument "a" violates contract. Expected: number Got: string
export default {
mounted: function () {
flowIt(20)
flowIt('bah') // Sees nothing wrong here
}
}
</script>
<style>...</style>
。。。
/*@flow*/
常量flowIt=(a:编号):编号=>{
返回a*10
}
flowIt(20)
flowIt('bah')//未捕获的TypeError:参数“a”的值违反了约定。应为:number get:string
导出默认值{
挂载:函数(){
flowIt(20)
flowIt('bah')//这里没有什么问题
}
}
...
最重要的是,我们的目标是不要因为流量而更改应用程序代码。理想情况下,我会像往常一样使用Vue:
<template>...</template>
<script>
/* @flow */
export default {
methods: {
flowIt (a: number): number {
return a * 10
}
},
mounted: function () {
this.flowIt(20)
this.flowIt('bah') // Should throw a type error.
}
}
</script>
<style>...</style>
。。。
/*@flow*/
导出默认值{
方法:{
flowIt(a:数字):数字{
返回a*10
}
},
挂载:函数(){
这是flowIt(20)
this.flowIt('bah')//应引发类型错误。
}
}
...
我不确定这是否与Vue有那么大的关系,就像我在Flow方面的经验一样(提示:没有那么丰富的经验)。我想我需要一些类型文件,使Flow“理解”Vue组件的结构(我猜指令也是如此)
对于那些对它有更多经验的人,您是如何让Flow正确使用Vue+webpack的?您仍然可以通过注释掉
、
和
部分,将Flow用于.Vue组件的JS部分:
/* @flow
<style>
...style definitions here
</style>
<template>
...html...
</template>
*/
// <script>
export default {
methods: {
flowIt (a: number): number {
return a * 10
}
},
mounted: function () {
this.flowIt(20)
this.flowIt('bah') //Won't throw error, as flowIt is attached to
//this.
}
}
// </script>
/*@flow
…这里是样式定义
…html。。。
*/
//
导出默认值{
方法:{
flowIt(a:数字):数字{
返回a*10
}
},
挂载:函数(){
这是flowIt(20)
this.flowIt('bah')//不会抛出错误,因为flowIt附加到
//这个。
}
}
//
即使在注释时,vue编译器仍会识别和节,但流类型检查器将忽略它们,只处理正确的javascript节
不幸的是,这并不能使您获得100%的类型覆盖率,因为Flow将无法检查附加到的函数和对象(Vue组件本身),但是,您仍然可以从Flow对外部函数(例如Vuex操作和getter、其他javascript导入模块)的调用的类型检查中获益,如果您在组件的方法中扩展了业务逻辑,那么在使用方法参数时可以获得某种类型安全性。此外,值得一提的是,将他的“注释”策略与运行时检查器相结合会使“包”更加完整。
一种方法是使用。这将使运行时检查器成为Web包/构建过程(保存时)+流检查的一部分,作为CI脚本的一部分
对于开发,tcomb将执行运行时检查并引发异常(控制台)。它不进行静态检查,因此
<script>
/* @flow */
const flowIt = (a: number): number => {
return '' // Sees nothing wrong here, should be a number
}
// Vue component
export default {
...
}
</script>
在包含@flow pragma的注释中包含模板和样式块;注释掉脚本标记(提到了这种方法):
我认为这已经在这段时间内解决了,现在您可以使用Vue组件的流,而无需黑客攻击。有关配置详细信息,请参阅这篇相当精彩的文章:
使用eslint+流量
这是集成flow&vue的另一种方法。
同时,flow
来到了eslint
。因此,我们可以直接将流量误差作为lint误差。这是一种更干净的方法,但随后流将与构建过程耦合(您不能单独运行流检查
,但需要通过webpack运行整个构建管道以获取错误)。截至2017年5月10日,.vue
文件中的全流支持仍在等待解决
在大多数情况下,这很好,但有些人可能仍然需要运行流检查的灵活性(和速度)。这也可能取决于您的CI设置
以下是如何设置flow和eslint:
安装deps
yarn add \
babel-plugin-syntax-flow \
babel-plugin-transform-class-properties \
babel-plugin-transform-flow-strip-types \
eslint \
babel-eslint \
eslint-plugin-html \
eslint-plugin-flowtype-errors \
eslint-plugin-vue \
eslint-config-vue \
flow-bin \
-D
配置.babelrc
{
...
"plugins": [
"babel-plugin-transform-class-properties",
"babel-plugin-syntax-flow",
"babel-plugin-transform-flow-strip-types"
]
}
配置.eslintrc
{
"parser": "babel-eslint",
"plugins": [
"html",
"flowtype-errors"
],
"extends": [
"vue"
],
"rules": {
"flowtype-errors/show-errors": 2
}
}
创建.flowconfig
文件。如果没有要配置的内容,则可以为空
在这种情况下,不需要其他解决方法,您只需在任何.vue
文件的脚本标记中使用/*@flow*/
。
请参阅原始帖子。我已经为vue
和flow
实现了一个项目模板。它支持单文件组件、linting、使用jest
进行测试、构建和服务器端渲染
vue
以下是您的组件的外观:
<template>
...
</template>
<script>
// @flow
import Vue from 'vue'
import { Store } from 'vuex'
import Component from 'nuxt-class-component'
import { Getter, State } from 'vuex-class'
import AppLogo from '~/components/AppLogo'
import Comment from '~/components/Comment'
import type { CommentType, StateType } from '~/types'
@Component({
components: {
AppLogo,
Comment
}
})
export default class Index extends Vue {
@State('comments') comments: Array<CommentType>
@Getter('hasComments') hasComments: boolean
fetch (
{ store, app }: { store: Store<StateType>, app: Vue }
): Promise<Array<CommentType>> {
// Uncomment the next line to test flow types:
// console.log(this.comments + 12)
return store.dispatch('fetchComments', app)
}
}
</script>
但请注意,仍然无法对某些部分进行注释。
在这里阅读更多关于已知问题的信息:这太糟糕了。我希望有一种方法可以获得100%的覆盖率,也许有一些流注释的魔力,但我开始相信没有。关于注释掉这些部分,使用babel插件typecheck,不需要注释掉模板和样式,因为它只检查脚本中的内容。它的工作原理与flow webpack插件或通过CLI运行flow有很大不同,但到目前为止,我没有遇到任何问题。我会再给它几天时间,如果没有其他关于如何实现这一点的建议,我会接受你
yarn add \
babel-plugin-syntax-flow \
babel-plugin-transform-class-properties \
babel-plugin-transform-flow-strip-types \
eslint \
babel-eslint \
eslint-plugin-html \
eslint-plugin-flowtype-errors \
eslint-plugin-vue \
eslint-config-vue \
flow-bin \
-D
{
...
"plugins": [
"babel-plugin-transform-class-properties",
"babel-plugin-syntax-flow",
"babel-plugin-transform-flow-strip-types"
]
}
{
"parser": "babel-eslint",
"plugins": [
"html",
"flowtype-errors"
],
"extends": [
"vue"
],
"rules": {
"flowtype-errors/show-errors": 2
}
}
<template>
...
</template>
<script>
// @flow
import Vue from 'vue'
import { Store } from 'vuex'
import Component from 'nuxt-class-component'
import { Getter, State } from 'vuex-class'
import AppLogo from '~/components/AppLogo'
import Comment from '~/components/Comment'
import type { CommentType, StateType } from '~/types'
@Component({
components: {
AppLogo,
Comment
}
})
export default class Index extends Vue {
@State('comments') comments: Array<CommentType>
@Getter('hasComments') hasComments: boolean
fetch (
{ store, app }: { store: Store<StateType>, app: Vue }
): Promise<Array<CommentType>> {
// Uncomment the next line to test flow types:
// console.log(this.comments + 12)
return store.dispatch('fetchComments', app)
}
}
</script>
type StateType = {
comments: string[]
}
function state (): StateType {
return {
comments: null
}
}
const getters = {
hasComments (state: StateType): boolean {
return Boolean(state.comments && state.comments.length > 0)
}
}
const mutations = {
'SET_COMMENTS': (
state: StateType, comments: string[]
) => {
state.comments = comments
}
}
const actions = {
async fetchComments (
{ commit, state }: ActionContext<StateType>
) {
const data = await Promise.resolve(['good', 'nice'])
commit('SET_COMMENTS', data)
// Uncomment next line to see typing in action:
// console.log(state.comments, state.fake)
return data
}
}