这篇文章会告诉你

它不会告诉你

  • 什么是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. 头文件string.h里的函数

    .strcpy 函数名: stpcpy 功 能: 拷贝一个字符串到另一个 用 法: char *stpcpy(char *destin, char *source); 程序例: #include &l ...

  2. Python 爬虫抓取代理IP,并检测联通性

    帮朋友抓了一些代理IP,并根据测试联的通性,放在了不通的文件夹下.特将源码分享 注意: 1,环境Python3.5 2,安装BeautifulSoup4  requests 代码如下: 1 2 3 4 ...

  3. 初学Python之 安装包的抉择~~

    上面的都是windows系统平台的安装包,哇,有没有后宫三千,不知道"临幸"哪一个的感觉~.~ 看了下面的你就明白啦. 毫无疑问,x86适合32位操作系统:x86-64适合64位操 ...

  4. Spring学习笔记之AOP配置篇(一)

    [TOC] 1. 创建并声明一个切面 首先,创建一个类,添加@Component注解使其添加到IoC容器 然后,添加@Aspect注解,使其成为一个切面 最后,在配置文件里面,使用<aop:as ...

  5. 【模板--完全背包】HDU--2602 Bone Collector

    Problem Description Many years ago , in Teddy's hometown there was a man who was called "Bone C ...

  6. java异常捕获的一点感悟

    class Annoyance extends Exception {} class Sneeze extends Annoyance {} class Human { public static v ...

  7. 黑科技:纯CSS定制文本省略

    作者:weilong,腾讯 web前端开发 工程师 商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处. WeTest导读 拿到设计MM的设计稿,Oh NO,点点点后面又双叒叕加内容了,弹丸 ...

  8. Spring (三)

    1.1 Spring的事务管理 1.1.1事务 事务:指的是逻辑上一组操作,要么全部成功,要么全部失败. 事务特性: 原子性:事务不可分割. 一致性:事务执行前后,数据完整性保存一致. 隔离性:一个事 ...

  9. shell变量的替换,命令的替换,转义字符

    1,shell变量的替换 变量可以根据变量是否为空或者被删除,而被替换为特定的值 ${var}  变量本来的值 $(var:-word)   如果变量为空,或者已被删除那么返回word,但是不改变va ...

  10. 【javascript】详解javascript闭包 — 大家准备好瓜子,我要开始讲故事啦~~

    前言: 在这篇文章里,我将对那些在各种有关闭包的资料中频繁出现,但却又千篇一律,且暧昧模糊得让人难以理解的表述,做一次自己的解读.或者说是对“红宝书”的<函数表达式/闭包>的那一章节所写的 ...