这篇文章会告诉你

它不会告诉你

  • 什么是vue,webpack

在创建vue项目时,官方推荐使用vue-cli这个命令行工具。原文是这么说的

# 全局安装 vue-cli
$ npm install --global vue-cli
# 创建一个基于 webpack 模板的新项目
$ vue init webpack my-project
# 安装依赖,走你
$ cd my-project
$ npm install
$ npm run dev

执行npm run dev 会运行webpack。大致会编译vue格式文件,热加载,eslint语法检测等功能。开发时过程带给我们非常省时省力的体验。

下面讲下当执行npm run dev后都发生了什么。

首先当通过vue-cli创建vue项目。执行的vue init webpack my-project

实际拷贝的是 https://github.com/vuejs-templates/webpack 中template提供的配置文件模版。他给我们提供了vue项目所需的架子并整合了webpack相关配置。

我们熟悉的build, src, config等目录都里面。

通过 package.json 可以看出有四个命令。

开发时要运行 npm run dev 或 npm run start 或 npm start

线上及生产环境要运行 npm run build

检测JS语法运行 npm run lint

  "scripts": {
"dev": "node build/dev-server.js",
"start": "node build/dev-server.js",
"build": "node build/build.js",
"lint": "eslint --ext .js,.vue src"
},

npm run dev实际执行的就是 node build/dev-server.js

打开dev-server.js,第一行是 require('./check-versions')()  先分析这个文件

check-versions.js

大致就是将当前运行的node和npm环境与package.json中的engines中node和npm要求的最低版本进行对比,看是否满足需求。

// 不错的node模块,使输出内容带前景色和背景色
var chalk = require('chalk')
// 语义化版本,详见http://semver.org/lang/zh-CN/
// https://www.npmjs.com/package/semver
var semver = require('semver')
var packageConfig = require('../package.json')
// 顾名思义,提供了一些和shell命令名字功能都一样的方法
var shell = require('shelljs')
function exec (cmd) {
return require('child_process').execSync(cmd).toString().trim()
} var versionRequirements = [
{
name: 'node',
// semver.clean(' =v1.2.3 ') => '1.2.3'
currentVersion: semver.clean(process.version),
versionRequirement: packageConfig.engines.node
},
] if (shell.which('npm')) {
versionRequirements.push({
name: 'npm',
currentVersion: exec('npm --version'),
versionRequirement: packageConfig.engines.npm
})
} module.exports = function () {
var warnings = []
for (var i = 0; i < versionRequirements.length; i++) {
var mod = versionRequirements[i]
if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
warnings.push(mod.name + ': ' +
chalk.red(mod.currentVersion) + ' should be ' +
chalk.green(mod.versionRequirement)
)
}
} if (warnings.length) {
console.log('')
console.log(chalk.yellow('To use this template, you must update following to modules:'))
console.log()
for (var i = 0; i < warnings.length; i++) {
var warning = warnings[i]
console.log(' ' + warning)
}
console.log()
process.exit(1)
}
}

打开package.json,你可以将

"engines": {
"node": ">= 4.0.0",
"npm": ">= 3.0.0"
},

改为

"engines": {
"node": ">= 4.0.0",
"npm": ">= 6.0.0"
},

然后运行 npm run dev 就会输出类似的错误

config/index.js

接着是var config = require('../config')

这里定义了一些开发环境和生产环境中不同的环境参数以及供后面的webpack配置文件使用的参数。

举个例子,为什么运行npm run dev会自动打开浏览器并且地址端口是8080。就是在这里面定义的。

更详细的参见:

https://github.com/vuejs-templates/webpack/blob/develop/docs/env.md

开发过程中可能需要调用后端的接口,如果要设置代理。

参见:

https://github.com/vuejs-templates/webpack/blob/develop/docs/proxy.md

本质上用到一个叫 http-proxy-middleware http代理中间件的node模块

// see http://vuejs-templates.github.io/webpack for documentation.
var path = require('path') module.exports = {
build: {
env: require('./prod.env'),
index: path.resolve(__dirname, '../dist/index.html'),
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
productionSourceMap: true,
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
// Run the build command with an extra argument to
// View the bundle analyzer report after build finishes:
// `npm run build --report`
// Set to `true` or `false` to always turn it on or off
bundleAnalyzerReport: process.env.npm_config_report
},
dev: {
env: require('./dev.env'),
port: 8080,
autoOpenBrowser: true,
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {},
// CSS Sourcemaps off by default because relative paths are "buggy"
// with this option, according to the CSS-Loader README
// (https://github.com/webpack/css-loader#sourcemaps)
// In our experience, they generally work as expected,
// just be aware of this issue when enabling this option.
cssSourceMap: false
}
}

env.js

dev.env.js 和 prod.env.js 里面放一些配置变量

比如我添加了一个KEY_ID

var merge = require('webpack-merge')
var prodEnv = require('./prod.env') module.exports = merge(prodEnv, {
NODE_ENV: '"development"',
KEY_ID: '123456'
})

在vue文件里就可以用process.env.KEY_ID 输出 123456

为什么? 原理是用到了webpack提供的 DefinePlugin 插件

  plugins: [
new webpack.DefinePlugin({
'process.env': config.dev.env
}),

注意字符串要写两个引号。

回到dev-server.js,接着分析webpack配置文件。这类的文章很多了,简要分析下

webpack.dev.conf

// 工具方法
var utils = require('./utils')
var webpack = require('webpack')
var config = require('../config')
// webpack官方提供的一个webpack配置文件合并工具
var merge = require('webpack-merge')
// 开发时和发布时公用的配置文件信息
var baseWebpackConfig = require('./webpack.base.conf')
// 一个webpack插件,生成入口html文件,最强大的功能是动态自动插入webpack生成的css和js资源文件
// 一般的单页面应用只有一个主html文件比如index.html,webpack打包生成js和css文件后,
// 我们当然可以在手动写标签引入这些资源文件,但有时候生成后的文件带有hash。如app-3d31retr.js。这时需要自动引入,并替换html。
var HtmlWebpackPlugin = require('html-webpack-plugin')
// 不解释,自行去github查文档
var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') // add hot-reload related code to entry chunks
Object.keys(baseWebpackConfig.entry).forEach(function (name) {
baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])
}) module.exports = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap })
},
// cheap-module-eval-source-map is faster for development
devtool: '#cheap-module-eval-source-map',
plugins: [
new webpack.DefinePlugin({
'process.env': config.dev.env
}),
// https://github.com/glenjamin/webpack-hot-middleware#installation--usage
new webpack.HotModuleReplacementPlugin(),
new webpack.NoEmitOnErrorsPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
}),
new FriendlyErrorsPlugin()
]
})

webpack.base.conf

主要讲下resolve部分,webpack把各种类型资源的文件当做module来处理,并通过相应的loader编译成js可运行的代码。

在vueLoaderConfig里已经定义了各种style loader了

  resolve: {
// 导入文件自动补全文件后缀
// 比如 src/index.js 中的 import App from './App'
// 完整的是import App from './App.vue'
extensions: ['.js', '.vue', '.json'],
// 别名映射,引入模块中可缩短字符串长度
// 如 import {playMode} from 'common/js/config' 可能实际是
// import {playMode} from '../../common/js/config'
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
'common': resolve('src/common'),
'components': resolve('src/components'),
'base': resolve('src/base'),
'api': resolve('src/api')
}
},
module: {
rules: [
// {
// test: /\.(js|vue)$/,
// loader: 'eslint-loader',
// enforce: 'pre',
// include: [resolve('src'), resolve('test')],
// options: {
// // 友好提供eslint未通过原因及链接
// formatter: require('eslint-friendly-formatter')
// }
// },
{
test: /\.vue$/,
// https://vue-loader.vuejs.org/zh-cn/configurations/pre-processors.html
loader: 'vue-loader',
// 最终结果类似,
/*
options: {
loaders: {
css: ['vue-style-loader', {
loader: 'css-loader',
options: {
minimize: false,
sourceMap: false
}
}],
postcss: ['vue-style-loader', {
loader: 'css-loader',
options: {
minimize: false,
sourceMap: false
}
}],
less: ['vue-style-loader', {
loader: 'css-loader',
options: {
minimize: false,
sourceMap: false
}
},
{
loader: 'less-loader',
options: {
sourceMap: false
}
}],
sass: ['vue-style-loader', {
loader: 'css-loader',
options: {
minimize: false,
sourceMap: false
}
},
{
loader: 'sass-loader',
options: {
indentedSyntax: true,
sourceMap: false
}
}],
scss: ['vue-style-loader', {
loader: 'css-loader',
options: {
minimize: false,
sourceMap: false
}
},
{
loader: 'sass-loader',
options: {
sourceMap: false
}
}],
stylus: ['vue-style-loader', {
loader: 'css-loader',
options: {
minimize: false,
sourceMap: false
}
},
{
loader: 'stylus-loader',
options: {
sourceMap: false
}
}],
styl: ['vue-style-loader', {
loader: 'css-loader',
options: {
minimize: false,
sourceMap: false
}
},
{
loader: 'stylus-loader',
options: {
sourceMap: false
}
}]
}
}
*/
options: vueLoaderConfig
},

为什么在vue中的style中定义 lang="stylus" 或  lang="less"  就能直接写相应的预处理语言啦。因为上面的webpack.base中已经把各种样式loader都定义好啦

为什么可以在vue类型类型里用 <template>, <script> 和 <style>。这是vue-loader的功劳。当然也离不开webpack。

详见:https://vue-loader.vuejs.org/zh-cn/start/spec.html

dev-server.js

// 检测是否满足版本需要
require('./check-versions')()
// 引入外层config中的index.js,分为运行时和开发时的变量信息
// 我们可以自己添加一些变量
var config = require('../config')
if (!process.env.NODE_ENV) {
// 最终变成 process.env.NODE_ENV = JSON.parse('"development"')
process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
} // 第三方模块。可调用系统默认的程序打开图片,地址等,如opn('http://localhost:8080'); open('./demo.jpg')
var opn = require('opn')
// node内置的核心模块
var path = require('path')
// node框架,在这里用来启动webserver
var express = require('express')
// 不解释,核心编译工具
// 官方文档中不推荐全局安装webpack,然后执行全局变量的方式
// 这里在nodejs里引入webpack,用提供的api来配置并启动
var webpack = require('webpack')
// http代理中间件,可转发api等
var proxyMiddleware = require('http-proxy-middleware')
var webpackConfig = require('./webpack.dev.conf')

简单说

开发用的webpack配置文件是 webpack.dev.conf.js + webpack.base.conf.js合并后的结果

主要实现热加载,友好的错误输出,方便调试等功能

生产环境用到的是webpack.prod.conf.js + webpack.base.conf.js合并后的结果

主要实现打包压缩css和js,不输出警告和错误

参见:

https://vue-loader.vuejs.org/zh-cn/workflow/production.html

总结:多看官方文档,多上github查资料。

https://github.com/vuejs-templates/webpack/blob/develop/docs/README.md

https://vue-loader.vuejs.org/zh-cn/

https://cn.vuejs.org/v2/guide/deployment.html

大致就是这些,有空再更。由于本人知识有限,文章有什么不对的,还请斧正~~~

vue-webpack-boilerplate分析的更多相关文章

  1. 一字一句的搞懂vue-cli之vue webpack template配置

    webpack--神一样的存在.无论写了多少次,再次相见,仍是初见.有的时候开发vue项目,对尤大的vue-cli感激涕零.但是,但是,但是...不是自己的东西,真的很不想折腾.所以,我们就得深入内部 ...

  2. 【原创】从零开始搭建Electron+Vue+Webpack项目框架,一套代码,同时构建客户端、web端(二)

    摘要:上篇文章说到了如何新建工程,并启动一个最简单的Electron应用.“跑起来”了Electron,那就接着把Vue“跑起来”吧.有一点需要说明的是,webpack是贯穿这个系列始终的,我也是本着 ...

  3. Vue源码分析(一) : new Vue() 做了什么

    Vue源码分析(一) : new Vue() 做了什么 author: @TiffanysBear 在了解new Vue做了什么之前,我们先对Vue源码做一些基础的了解,如果你已经对基础的源码目录设计 ...

  4. vue+webpack实践

    最近使用了vue来做SPA应用,记一波学习笔记. 使用vue+webpack实现前端模块化. vuejs——轻量.学习成本低.双向绑定.无dom的操作.组件的形式编写 推荐官方文档 vue.js官方文 ...

  5. windows环境下搭建vue+webpack的开发环境

    前段时间一直在断断续续的看vue的官方文档,后来就慢慢的学习搭建vue的开发环境,已经有将近两周了,每到最后一步的时候就会报错,搞的我好郁闷,搁置了好几天,今天又接着搞vue的开发环境,终于成功了.我 ...

  6. Vue + Webpack + Vue-loader 1

    Vue + Webpack + Vue-loader 原文地址:https://lvyongbo.gitbooks.io/vue-loader/content/ Vue-loader 是什么? vue ...

  7. Vue实战Vue-cli项目构建(Vue+webpack系列之一)

    用Vue比较长一段时间了,大大小小做了一些项目,最近想总结一下知识点,出一个Vue+webpack系列,先从项目构建说起--vue-cli. 由于是Vue+webpack这里就不赘述git那些东西,默 ...

  8. 从零开始:一个正式的vue+webpack项目的目录结构是怎么形成的

    如何从零开始一个vue+webpack前端工程工作流的搭建,首先我们先从项目的目录结构入手.一个持续可发展,不断加入新功能,方便后期维护的目录结构究竟是长什么样子的?接下来闰土大叔带你们一起手摸手学起 ...

  9. 前端Vue 源码分析-逻辑层

    Vue 源码分析-逻辑层 预期的效果: 监听input的输入,input在输入的时候,会触发 watch与computed函数,并且会更新原始的input的数值.所以直接跟input相关的处理就有3处 ...

  10. vue学习:vue+webpack的快速使用指南(新手向)

    一.vue有两种使用方式: 1.下载vue.js <script src="vue.js"></script> 2.使用npm npm install vu ...

随机推荐

  1. 又见angular----步一步做一个angular4小项目

    这两天看了看angular4的文档,发现他和angular1.X的差别真的是太大了,官方给出的那个管理英雄的Demo是一个非常好的入门项目,这里给出一个管理个人计划的小项目,从头至尾一步一步讲解如何去 ...

  2. SpringMVC+MyBatis 事务管理二

    前言 上篇主要从编程式事务和声明式事务注解的形式来了解了事务,而这篇我们针对AOP的方式来实现事务.先回顾下事务的基础知识事务的隔离级别和事务的传播行为.使用aop 配置事务时注意引用aspectjw ...

  3. FasfDFS整合Java实现文件上传下载

    文章目录     一 : 添加配置文件     二 : 加载配置文件         1. 测试加载配置文件         2. 输出配置文件     三:功能实现         1.初始化连接信 ...

  4. swift3.0 UITableView侧滑支持多选项

    func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableVie ...

  5. 关于Wifi室内定位应用中的一些问题:

    公司目前在办公室内布设了一套室内定位的实验环境,用的是华为路由器,采用的算法是基于信号强度的RSSI算法.公司目前希望能使用这套设备得到无线网络覆盖范围下的所有移动设备(对应每个人)的MAC地址,同时 ...

  6. HTML学习笔记2

    5.超链接 3种超链接: 1. 连接到其他页面 2. 锚: (是链接页面)指给超链接起一个名字,作用是连接到本页面或者其他页面的特定位置.使用name属性给超链起名字,本页要加# 3. 连接到邮件: ...

  7. 浅谈Python在信息学竞赛中的运用及Python的基本用法

    浅谈Python在信息学竞赛中的运用及Python的基本用法 前言 众所周知,Python是一种非常实用的语言.但是由于其运算时的低效和解释型编译,在信息学竞赛中并不用于完成算法程序.但正如LRJ在& ...

  8. 【LeetCode】数组-1(643)-返回规定长度k的最大子数组的平均数

    好久没有刷LeetCode了,准备重拾并坚持下去,每天刷个两小时.今天算是开始的第一天,不过出师不利,在一道很简单的题目上墨迹半天.不过还好,现在踩过的坑,应该都不会白踩,这些可能都是以后程序员路上稳 ...

  9. 设计模式之Adapter模式

    说起Adapter,STL里的stack和queue都是adapter,底层是deque,隐藏了deque的一些接口,使得其可以达到FIFO是queue,LIFO是stack. The STL sta ...

  10. MFC加载PNG图片并实现双缓冲

    因为PNG包含Alpha通道,所以不同于BITMAP,在MFC中使用CImage类对其进行处理,通常使用load和draw成员函数. 所以标题的论述可以进一步解释为,使用CImage实现双缓冲. 通常 ...