vue-cli

vue-cli是一种基于vue.js进行快速开发的完整系统,通过@vue/cli+ @vue/cli-service-global快速开始零配置原型开发,能够用于 快速原型设计简化应用程序搭建进行高效项目管理。它由主要的三个组件组成:

  • 通过@vue/cli搭建项目脚手架。cli是一个全局安装的npm包,提供了终端里的vue命令,可以由此创建一个项目脚手架(vue create)、构建新想法的原型(vue serve)及图形化界面管理项目(vue ui)。

  • 运行时依赖@vue/cli-service它是一个npm包,局部安装在每个@vue/cli创建的项目中,构建于webpackwebpack-dev-server之上。项目内部的vue-cli-service命令,提供servebuildinspect实现开发打包检查内部webpack配置功能。

  • 通过cli插件进行扩展。cli插件是向vue项目提供可选功能的npm包,名字以@vue/cli-plugin-(内置插件)vue-cli-plugin-(社区插件)开头,开发中通过vue add命令添加。在项目中运行vue-cli-serviec命令时,会自动解析并加载package.json中列出的所有cli插件。

开发

安装

安装命令

npm install -g @vue/cli

检查版本

vue --version //3.10.0

快速原型开发

安装全局依赖

npm install -g @vue/cli-service-global

使用vue servevue build命令对单个*.vue文件进行快速原型开发

vue serve fileName //开发环境下为js/vue文件启动一个服务器
vue build fileName //生产环境零配置构建一个js/vue文件

创建项目

运行以下命令创建一个项目,可以根据提示选取默认配置(babel+eslint)和手动选择需要的特性

vue create 项目名

配置

webpack基础相关

基本概念

webpack是一个js的静态模块打包工具。对于webpack来说,一切文件皆为模块,处理应用程序时会在内部构建一个依赖图,会从main.js出发,识别出源码中的模块化导入语句,递归地找出入口文件的所有依赖,将其打包生成一个或多个bundle
| 概念 | 用途 |
| :-------- | :--------|
| entry|webpack将这个模块作为构建内部依赖的开始|
| module| webpack中一切皆模块|
| chunk| 一个chunk由多个模块组合而成,用于代码合并与分割|
| loader|模块转换器,将非js内容按需转换。test用于标识被转换的文件,use指示文件被转换时应该使用的loader,并且在数组中从右到左地解析执行|
| plugin|解决loader无法实现的其他事情,是一个具有apply方法的js对象,apply方法会被webpack complier调用,且complier对象可在整个编译声明周期访问。由于插件可以携带参数/选项,必须在webpack配置中,向plugin传入new实例。如html-webpack-plugin为应用程序生成一个html文件,并自动注入所有生成的bundle|
| output|告诉webpack在哪里输出它所创建的bundle,以及如何命名这些文件,生成文件默认放置在./dist文件夹中|

//ConsoleLogOnBuildWebpackPlugin.js
const pluginName = 'ConsoleLogOnBuildWebpackPlugin'

class ConsoleLogOnBuildWebpackPlugin{
  apply(compiler){//compiler hook的tap方法的第一个参数,应为驼峰式命名的插件的名称,建议为此使用一个常量,以便可以在所有hook中复用
    complier.hooks.run.tap(pluginName, compilation = {
      console.log('webpack构建过程开始')
    })
  }
}

配置示例

// build/webpack.base.config.js
const path = require('path')
const webpack = require('webpack')
module.exports = {
  entry: './src/js/main.js'
  module: {
    rules:[
      { test: /\.vue$/, use: 'vue-loader'}
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({template: './src/index.html'})
  ],
  output: {
    path: path.resolve(__dirname,'dist'),
    filename: 'js/[name].js'
  }
}

解析原理

在使用webpack构建的应用程序中,主要有三种类型的代码:

  • 与业务有关的代码;
  • 代码依赖的第三方库;
  • webpackruntimemanifest,管理所有模块交互。

runtime,及伴随的所有manifest数据,是指在浏览器运行过程中,webpack用来连接模块化应用程序所需的所有代码,即指在模块交互时,连接模块所需的加载和解析逻辑,包括已经加载到浏览器中的连接模块逻辑和尚未加载模块的延迟加载逻辑。

compile开始执行、解析和映射应用程序时,会保留所有模块的详细要点,这个数据集合称为manifest,当完成打包并发送到浏览器时,runtime会通过manifest来解析和加载模块。无论选择哪种模块语法,importrequire语句转换为__webpack_require__方法,此方法指向模块标识符(module identifier),通过使用manifest中的数据,runtime将能够检索这些标识符,找出每个标识符背后对应的模块。

通过使用内容散列(content hash)作为bundle文件的名称,在文件内容修改时,会计算出新的hash,浏览器会使用新的名称加载文件,从而使缓存无效。这这样即使内容没有明显修改,某些hash还是会改变,因为注入的runtimemanifest在每次构建后都会发生变化。

loader和插件相关

每个cli插件会包含一个(用来创建文件的)生成器和一个(用来调整webpack核心配置和注入命令的)运行时插件。使用vue create创建新项目时,部分插件会根据预设特性被预安装好,如果想在创建好的项目中安装一个插件,使用vue add @vue/eslint,这个命令将@vue/eslint解析为完整的包名@vue/cli-plugin-eslint,然后从npm安装它,调用它的生成器。

调整webpack配置最简单的方式是vue.config.js中的configureWebpack选项提供一个对象,这个对象会被webpack-merge合并入最终的webpack配置。如果需要基于环境有条件地配置行为,或者想要直接修改配置,就换成一个函数(函数环境变量被设置之后懒执行),可以直接使用config参数来修改webpack中的配置,或者返回一个对象进行merge处理。还可以使用chainWebpack改变webpack内部配置,这种方式是链式修改,而configureWebpack倾向于整体替换和修改

//vue.config.js
module.exports = {
  configureWebpack: config => {
    if(process.env.NODE_ENV === 'production'){
      //为生产环境修改配置
    } else {
      //为开发环境修改配置
    }
  }
}

vue-cli内部的webpack配置是通过webpack-chain维护,它可以定义具名的loader规则和插件,并且可以在后期进入这些规则并对他们的选项进行修改。

loader

  • 修改loader选项。对于css相关loader来说,推荐使用css.loaderOptions而不是直接链式指定loader,是因为每种css文件类型都有多种规则,而css.loaderOprtions可以确保通过一个地方影响所有规则。
//vue.config.js
module.exports = {
  chainWebpack: config => {
    config.module
    .rule('vue')
    .use('vue-loader')
      .loader('vue-loader')
      .tap(optopns => {
        //修改它的选项
        return options
      })
  }
}

  • 添加一个新的loader
//vue.config.js
module.exports=  {
  chainWebpack: config => {
    //GraphQL Loader
    config.module
    .rule('graphql')
    .test(/\.graphql$/)
    .use('ggraphql-tag/loader')
      .loader('graphql-tag/loader')
      .end()
  }
}
  • 替换一个规则里的loader
//vue.config.js
module.exports = {
  chainWebpack: config => {
    const svgRule = config.module.rule('svg')
    svgRule.uses.clear()
    //清除所有的loader,否则接下来的loader会附加在该规则的所有loader之后
  }
  svgRule
    .use('vue-svg-loader')
      .loader(vue-svg-loader)
      //添加要替换的loader
}

插件

  • 使用插件
//vue.config.js
module.exports = {
  chainWebpack: config => {
    config.plugin('assetToJson')
    .use(AssetsWebpackPlugin, [
      {/*配置项*/}
    ])
  }
}
  • 修改插件选项
//vue.config.js
module.exports = {
  chainWebpack: config => {
    config.plugin('html')
    .tap(args => {
      return [/*传递给html-webpack-plugin构造函数的新参数*/]
    })
  }
}

可以通过vue inspect来确认变更,vue-cli-service暴露了inspect用于审查解析好的webpack配置,全局的vue可执行程序同样提供了inspect命令,会将解析出来的webpack配置、包括链式访问规则和插件的提示打印到stdout,也可以将其输出重定向到一个文件以便进行查阅

vue inspect > output.js

page相关

相较于vue cli2vue cli3搭建的项目中没有config目录和build目录,默认封装了项目运行常用的webpack常用配置,可以通过vue inspect plugins查看默认插件及用途。添加自定义配置需要在根目录中手动添加vue.config.js文件,它会被@vue/cli-service自动加载。

multi-page模式下构建应用,每个page应该有一个对应的js入口文件,它的值是一个对象,key是入口的名字,值是包括entry(必选)、templatefilenametitlechunks的字符串

//vue.config.js
module.export = {
  pages: {
  index: {
    entry: 'src/index/main.js', //入口
    template: 'public/index.html', //模板
    filename: 'index.html', //在dist/index.html的输出
    title: 'Index Page',
    chunks: ['chunk-vendors','chunk-common','index'],//页面中包含的块,通常包含提取出来的通用块和依赖块
  }
  }
}

css相关

webpack不支持原生解析css文件,如果要支持非js类型的文件,需要使用loader机制,本质上是一个模块转换器,将模块内容按需转换。

css modules

是一个用于模块化和组合css的系统,若想在js中导入css或其他预处理文件,文件应以.module.(css|less|sass|scss|styl)结尾,若想去掉文件名的.moudle,设置vue.config.jscss.modulestrue,通过