Vue.js 开发不完全指南

12/9/2018
0
Vue

开发阶段

这个项目是一款中后台管理系统,所以当时以 Vue.js 作为主框架进行开发,然后使用了 iView 作为 UI 框架。其中,其它部分就是 Vue 的生态了,例如 Vue Router 和 Vuex 等。

生成项目结构

最近 @vue/cli 发布了正式版 Vue CLI 3,但其实早在 3 月份就发布了测试版,所以当初使用了测试版 CLI 生成了项目结构。最近也升级成和最新版一致的了。CLI 工具还增加非常强大的功能,包括安装插件、可视化界面、配置文件等。

// 生成项目结构
vue create project-name

// 使用 UI 界面
vue ui

这部分就比较简单,关于项目结构,CLI 文档也有说明。

配置开发环境

最新版的 CLI 工具支持自定义配置,如果你在项目根目录下提供一个 vue.config.js 文件,cli 在启动项目时会自动加载这些配置项。这部分应该是比较有趣的一部分,而且把这些东西配置好之后,开发效率可以嗖嗖嗖的提升。

这一项里面,我最常用的是端口号和代理这两项,webpack-dev-server 支持的配置项都可以集成进来。需要代理的原因是前后台是分离式开发,需要解决跨域问题(如果后台配置了 CORS,则不需要这项配置)。

module.exports = {
  //...
  devServer: {
    port: 8081,
    proxy: 'http://localhost:8080',
  },
  //...
}

使用 webpack 插件

使用 webpack 插件比较简单,例如使用 webpack-bundle-analyzer 来分析打包后各个模块的体积大小:

const BundleAnalyzerPlugin =
  require('webpack-bundle-analyzer').BundleAnalyzerPlugin

module.exports = {
  plugins: [new BundleAnalyzerPlugin()],
}

webpack 链式操作 chainWebpack

这个配置项允许你对内部的 webpack 配置做出一些修改,例如添加一个新的 loader、修改插件的配置、为其它目录添加 vue 的支持等。但是 问题在于你可能不知道内部使用的 loader,那么这时候 vue inspect 这个命令会将内部配置输出在控制台,你可以查看想要修改的规则。看一下这个 🌰:

// vue.config.js

// 修改 index.html 和 favicon.png 的路径
module.exports = {
  chainWebpack: (config) => {
    config.plugin('html').tap((args) => {
      args[0].template = 'path/to/index.html'
      args[0].favicon = 'path/to/favicon.png'
      return args
    })
  },
}

这个功能使用了 webpack-chain 的 API。

使用环境变量

如果你想在项目中使用环境变量,可以在项目的根目录下增加以下文件:

  • .env 所有环境加载
  • .env.local 所有环境 加载,会被 git 忽略
  • .env.[mode] 在特定环境中加载
  • .env.[mode].local 在特定环境中加载,会被 git 忽略

其中 mode 的值 可以是:development/production/test

如何使用呢?假如在项目根目录下存在 .env 文件:

VUE_APP_TITLE=Hello World

此时,在项目代码中就可以这样访问它:

console.log(process.env.VUE_APP_TITLE) // Hello World

如果运行 yarn build 进行构建,那么这个环境变量将会直接被替换对应的值。

浏览器兼容

如果要兼容 IE 则 需要安装 babel-polyfill

// main.js
import 'babel-polyfill'
// ...

使用 JSX

提到 JSX,最先想到的是 React。其实 JSX 是可以独立存在的,它只是一种语法糖而已。所以在 Vue 中也可以使用。在 Vue CLI 3 中可以直接使用 JSX,而 2.x 版本则需要安装相应的依赖(babel-plugin-transform-vue-jsx)。

我们项目的 UI 框架是 iView,在使用 Table 组件时经常要使用 render 函数,如下:

export default {
  data() {
    return {
      columns: [
        {
          title: '操作',
          key: 'action',
          render: (h, params) => {
            return h('div', [h('Button', '编辑'), h('Button', '删除')])
          },
        },
      ],
    }
  },
}

但是如果 render 函数要处理很多元素的时候,它会显得非常臃肿,而且不易维护。那此时我们就可以使用 JSX 来优化代码:

export default {
  data() {
    return {
      columns: [
        {
          title: '操作',
          key: 'action',
          render: (h, params) => {
            return (
              <div>
                <i-button>编辑</i-button>
                <i-button>删除</i-button>
              </div>
            )
          },
        },
      ],
    }
  },
}

注:如果你使用的是 Webstorm,可能会出现语法错误之类的警告。可以通过设置 Settings -> Languages & Frameworks -> Javascript -> Javascript language version -> React JSX 来解除报错。

性能优化

代码分割 & 路由懒加载

代码分割是什么意思呢?正常来说,在你使用 yarn build 构建之后, dist 文件下会生成一个如几个文件,默认情况下没有开启代码分割。

dist-js

例如有如下路由:

import Home from './views/Home.vue'
import About from './views/About.vue'

const routes = [
  {
    path: '/home',
    name: 'home',
    component: Home,
  },
  {
    path: '/about',
    name: 'About',
    component: About,
  },
]

export default routes

这是我们经常使用的路由加载方式,没有代码分割。那我们如何使用代码分割功能呢? 这时我们就可以根据路由对代码进行分割了:

const routes = [
  {
    path: '/home',
    name: 'home',
    component: () => import(/* webpackChunkName: "home" */ './views/Home.vue'),
  },
  {
    path: '/about',
    name: 'About',
    component: () =>
      import(/* webpackChunkName: "about" */ './views/About.vue'),
  },
]

export default routes

这样改造完之后,我们再运行 yarn build

dist-chunk-js

在原来的基础上又增加了 2 个 js 文件和 2 个 css 文件,这正是代码分割的作用。只有在访问相应路由时再去加载对应的 js 和 css 文件。

分析并压缩代码体积

在编写大型程序时,难免会遇到打包后 js 文件体积过大的问题,因为项目可能会引入第三方依赖,在一定程度上加重了这个问题。那如何解决呢?

  1. 代码分割,按需加载
  2. 分析打包后的代码
  3. 剥离第三方库

首先,代码分割上面已经说了。

如何分析打包后的代码呢?运行 yarn build 时提供参数 --report

yarn build --report

运行上述命令之后,会在 dist 下生成 report.html,打开它可以看到:

build-report

 各个色块代表了相应的 js 所占用的空间。面积越大的体积就越大。

那如何优化呢?在使用了路由懒加载之后,性能会有比较明显的提升。但是我们还需要进一步优化:剥离第三方库。

 何为剥离?因为项目使用 iView 作为 UI 框架,然后还有 Vuex 和 vue-router 这几个 依赖框架。 正常情况下,这些框架和其他一些依赖都会被打包进 dist/chunk-venders.[hash].js 中,因此, 可能会得到一个很大(5M+)的 js 文件。但是我们可以通过将这些 js 以 CDN 的方式引入,这样 就可以避免 chunk-venders.[hash].js 文件过大:

// vue.config.js
module.exports = {
  // ...
  configureWebpack: {
    externals: {
      vue: 'Vue',
      vuex: 'Vuex',
      'vue-router': 'VueRouter',
      iview: 'iview',
    },
  },
}

public/index.html 中添加以下内容:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0" />
    <link rel="icon" href="<%= BASE_URL %>favicon.ico" />
    <!-- 要添加的 css -->
    <link
      rel="stylesheet"
      href="https://unpkg.com/[email protected]/dist/styles/iview.css"
    />
    <!-- 要添加的 css -->
    <title>vue-test-demo</title>
  </head>
  <body>
    <noscript>
      <strong
        >We're sorry but vue-test-demo doesn't work properly without JavaScript
        enabled. Please enable it to continue.</strong
      >
    </noscript>
    <div id="app"></div>
    <!-- 要添加的 js -->
    <script src="https://unpkg.com/[email protected]/dist/vue.runtime.min.js"></script>
    <script src="https://unpkg.com/[email protected]/dist/vuex.min.js"></script>
    <script src="https://unpkg.com/[email protected]/dist/vue-router.min.js"></script>
    <script src="https://unpkg.com/[email protected]/dist/iview.js"></script>
    <!-- 要添加的 js -->
    <!-- built files will be auto injected -->
  </body>
</html>

如果是其它的第三方库,写法都一样。再次运行 yarn build 之后, 可以看到 chunk-venders.[hash].js 文件的体积会明显变小。

启用 gzip

HTTP 协议中的 gzip 是用来改进性能的,它的压缩比率大概在 3 到 10 倍之间,可以大幅节省网络带宽,但是会增加服务器 CPU 的负担。目前主流浏览器都支持 gzip 解码,所以一般只需要服务端启用 gzip 即可。


商业转载请联系站长获得授权,非商业转载请注明本文出处及文章链接,您可以自由地在任何媒体以任何形式复制和分发作品,也可以修改和创作,但是分发衍生作品时必须采用相同的许可协议。
本文采用 CC BY-NC-SA 4.0 - 非商业性使用 - 相同方式共享 4.0 国际进行许可。