解析 vue-cli 如何构建项目

vue-cli

用 vue-cli 直接生成一个 vue 项目很简单方便,不过要想深入学习并掌控 vue 项目,了解项目是如何建构的是很必要,今天就来一边学习一边试着分析。

本文 vue-cli 版本 2.9.6

一、初始化目录结构

vue 主要文件目录:

  1. build (构建项目相关代码)
  2. config (项目开发环境配置)
  3. src (代码目录)
  4. static (静态资源)
  5. index.html (访问的主页面)
  6. package.json (项目基本信息、依赖信息)

通常 src 存放源代码,static 存放静态资源,package.json 存放项目信息以及依赖信息,config 存放配置文件,通过 build 的脚本文件,使用依赖 vue-loader 解析源代码的 vue 文件转化成 js 文件,压缩代码,合并 html 并引入相关 js 文件及资源文件,生成项目文件等操作。

这次主要讲讲 package.json、build 以及 config 文件

二、package.json 文件

{
  ......
  ......
  ......
  "scripts": {		//npm 命令
    "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
    "start": "npm run dev",
    "build": "node build/build.js"
  },
  "dependencies": {		//运行时依赖(生产环境)
    "vue": "^2.5.2",
    "vue-router": "^3.0.1"
  },
  "devDependencies": {		//开发时依赖(开发环境)
      ......
      ......
  },
  ......
  ......
}

scripts

scripts 定义的是用 node 执行的命令
如:npm run build,就是执行了 build/build.js 文件,
npm run dev,就是执行了 build/webpack.dev.conf.js 文件

dependencies vs devDependencies

dependencies 是运行时依赖(生产环境)       npm install --save  **(package name)
devDependencies 是开发时的依赖(开发环境)  npm install --save-dev  **(package name)

dependencies 存放的是本地运行所需的文件,像 babel(JavaScript 转化) 和 vue-loader(vue 文件转化)等依赖

dependencies 存放的是打包时需要运行的依赖

三、 config 文件(项目开发环境配置)

内部目录:
(1) dev.env.js 设置开发环境变量
(2) index.js
(3) prod.env.js 设置生产环境变量

config 文件主要是一些配置环境,重点说说 index.js 文件,其他两个都只有一句代码,设置一个变量表示开发或者生产环境。

index.js

module.exports = {
  // 开发模式配置
  dev: {
    // 文件路径
    assetsSubDirectory: 'static', 	// 资源引用路径
    assetsPublicPath: '/',    		// 生成 index.html 路径
    proxyTable: {     	// 代理
      'xxx': {        	// 代理名称(请求路径带上这个名称时自动转换)
          target: 'xxx',   		 // 代理服务器地址
          changeOrigin: true,
          secure: false,
          pathRewrite: {  
                '^/xxx': '/xxx'   // 请求路径重写        
          }
      }
    },   

    // 服务器设置
    host: 'localhost',	// 测试页面地址
    port: 8080, 		// 测试页面端口号
    autoOpenBrowser: true, // 开启服务器时是否自动打开浏览器

    // 映射
    devtool: 'cheap-module-eval-source-map',

    cssSourceMap: true  //是否开启css映射
  },

  //生产环境配置
  build: {
    // 生成 index.html 模板位置
    index: path.resolve(__dirname, '../dist/index.html'),

    // 路径
    assetsRoot: path.resolve(__dirname, '../dist'),   //生成项目位置
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',

    // 映射
    productionSourceMap: true,
    devtool: '#source-map',

    productionGzip: false,  	// 用于 gzip 压缩判断,看 webpack.prod.conf.js 文件讲解
    productionGzipExtensions: ['js', 'css'],

    // npm run build --report 构建完成后查看bundle analyzer报告
    // process.env 是 node 的全局变量,这里用来读取 npm 命令后面的值 report 
    // 用于 webpack.prod.conf.js 文件做判断值
    bundleAnalyzerReport: process.env.npm_config_report
  }
}

四、build 文件(构建项目)

内部目录:
(1) build.js 打包编译入口
(2) check-version.js 检查版本
(3) utils.js 工具代码
(4) vue-loader.conf.js vue-loader 配置
(5) webpack.base.conf.js 基础配置文件
(6) webpack.dev.conf.js 开发环境配置文件
(7) webpack.prod.conf.js 生产模式配置文件

check-version.js 用于检查版本,被引入各个文件之中
utils.js 是工具代码,会设置 css-loader、postcss-loader 等
vue-loader.conf.js 则是配置 vue-loader 解析 vue 文件

重点在其他几个文件

webpack.base.conf.js 基础配置文件

module.exports = {
  context: path.resolve(__dirname, '../'),  // 目录 
  entry: {   		 // 入口文件
    app: './src/main.js'
  },
  output: {  		 // 输出内容
    path: config.build.assetsRoot,
    filename: '[name].js',
    publicPath: ......
  },      
  resolve: {
    extensions: ['.js', '.vue', '.json'],   // 检测文件后缀
    alias: {   	 // 指定路径的别名,在引用文件路径中,如果有别名的符号,会被替换成指定的路径。
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
    }
  },
  module: {
    rules: [    // 解析规则配置
    	vue-loader		// vue-loader 解析 vue 文件输出 js 模块 
    	babel-loader	// babel-loader 转换 ES6
    	url-loader		// url-loader 把一定大小内的资源变成base64格式
	]
  }
}

webpack.dev.conf.js 开发环境配置文件

const devWebpackConfig = merge(baseWebpackConfig, {	// 合并之前的基础配置文件
  module: {		// 增加cssSourceMap的功能
    rules: utils.styleLoaders({ ...... })
  },
  devtool: config.dev.devtool,	// 定义开发模式,cheap-module-eval-source-map使得开发更快

  devServer: {	// 定义服务器的一些配置
  	......	
  	......
  },
  plugins: [	// 插件
    DefinePlugin				// 定义 process.env(开发环境)
   	HotModuleReplacementPlugin	// 模块热替换插件
	NamedModulesPlugin			// 显示模块加载相对路径插件
    NoEmitOnErrorsPlugin		// 进程遇到错误代码将不会退出,在控制台输出错误日志
	HtmlWebpackPlugin			// 使用插件生成一个指定的模版
    CopyWebpackPlugin			// 自定义静态资源目录
  ]
})

webpack.prod.conf.js 生产模式配置文件

打包到生产环境,和 webpack.dev.conf.js 一样也是先合并基础配置文件,但是插件有些变化。

1.新增了 output 配置,将源码打包成带有 hash 尾缀的不同模块的 js 文件,如 vendor.cd57a1ba620b10849fab.js 。
这里使用 chunkhash 尾缀,根据文件映射,在修改时如果没有修改到当前模块或者当前引用的模块, chunkhash 就不会改变,从而在部署的时候可以减少文件缓存带来的部署问题,是一个优化方案。

output: {
    path: config.build.assetsRoot,
    filename: utils.assetsPath('js/[name].[chunkhash].js'),
    chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
  },

2.插件

DefinePlugin				定义 process.env(生产环境)
UglifyJsPlugin				代码压缩
OptimizeCSSPlugin			压缩css代码
HtmlWebpackPlugin			生成主页面模板
HashedModuleIdsPlugin		根据模块的相对路径生成一个 hash 作为模块 id
ModuleConcatenationPlugin	作用域提升,加快代码执行速度
CommonsChunkPlugin			提取第三方库和公共模块

// 抽离css代码(webpack打包 css会变成用 js的模块方式引入,有延迟,所以要抽离css)
// 为该文件增加 contenthash 尾缀(contenthash:当前模块的内容变了,hash值才改变)
new ExtractTextPlugin({
  filename: utils.assetsPath('css/[name].[contenthash].css'),
  allChunks: true,
}),

额外要注意的插件:

// gzip 压缩插件
if (config.build.productionGzip) {		// 判断生产模式下的 productionGzip 值
  // 提供带 Content-Encoding 编码的压缩版的资源
  const CompressionWebpackPlugin = require('compression-webpack-plugin')

  webpackConfig.plugins.push(	// 把此插件插入 webpack 插件设置内
    new CompressionWebpackPlugin({ ......	})
  )
}

// 查看 bundle analyzer 报告插件
if (config.build.bundleAnalyzerReport) {	// 在config/index.js中已说明,npm 输入的命令
  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}

顺便小结一下文件尾缀:

尾缀状态变动使用
hash文件变动,立即改变图片等资源
chunkhash修改到当前模块或者当前引用的模块才改变常用于 js
contenthash当前模块的内容变了,值才改变常用于 css

build.js

项目打包时执行的文件,npm run build

主要是先删除(rimraf 插件)以前打包的 dist 文件,删除后读取 webpack.prod.conf.js 的设置然后开始 webpack 的构建

五、总结

最后总结一下整个 vue 项目构建流程(主体为 webpack 的构建流程)

启动构建,读取与合并配置参数,加载 Plugin

使用 Loader 递归翻译所有模块。这里是 vue-loader 解析 vue 文件,变成 js 文件 module.exports 大概三个语言模块(html,script,style)。中间穿插 es6 转换,css 转换,资源文件引用增加 hash 尾缀以及 base64 格式转化。

根据依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表。即打包压缩、抽取插件和公共代码,生成 app.[chunkhash].js 、按需加载.[chunkhash].js、vendor.[chunkhash].js 和 manifest.[chunkhash].js

文件来源
app源代码
vendor抽离 node_modules 依赖及公共模块
manifest映射各个模块的数据集合,便于快速更替文件

最后生成主页面模板引入相关静态资源和 js 文件,把项目输入到 dist 文件夹内。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值