Vue-Cli目录结构详解

vue-cli脚手架工具就是为我们搭建了开发所需要的环境,为我们省去了很多精力。有必要对这个环境进行熟悉,本文主要介绍项目的目录结构。

目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
├─build                 // 保存一些webpack的初始化配置,项目构建
│ ├─build.js // 生产环境构建
│ ├─check-version.js // 检查npm、node版本
│ ├─vue-loader.conf.js // webpack loader配置
│ ├─webpack.base.conf.js// webpack基础配置
│ ├─webpack.dev.conf.js // 开发环境配置,构建本地开发服务器
│ ├─webpack.prod.conf.js// 生产环境的配置

├─config // config文件夹保存一些项目初始化的配置
│ ├─dev.env.js // 开发环境的配置
│ ├─index.js // 项目一些配置变量
│ ├─prod.env.js // 生产环境的配置

├─dist // 打包后的项目
├─node_modules // 依赖包

├─src // 源码目录
│ ├─assets // 静态文件目录
│ ├─components // 组件文件
│ ├─router // 路由
│ ├─App.vue // 是项目入口文件
│ ├─main.js // 是项目的核心文件,入口
├─static // 静态资源目录
├─.babelrc // Babel的配置文件
├─.editorconfig // 代码规范配置文件
├─.gitignore // git忽略配置文件
├─.postcssrc.js // postcss插件配置文件
├─index.html // 页面入口文件
├─package-lock.json // 项目包管控文件
├─package.json // 项目配置
└─README.md // 项目说明书

详解

build目录

这个目录包含实际为开发环境与生产环境的webpack配置文件。通常你不需要关注这些文件,除非你想自定义webpack的loader,这样的话,应当先看看build/webpack.base.conf.js这个文件。

dev-server.js

首先来看执行npm run dev时候最先执行的build/dev-server.js文件。该文件主要完成下面几件事情:

  • 检查node和npm的版本、引入相关插件和配置
  • webpack对源码进行编译打包并返回compiler对象
  • 创建express服务器
  • 配置开发中间件(webpack-dev-middleware)和热重载中间件(webpack-hot-middleware)
  • 挂载代理服务和中间件
  • 配置静态资源
  • 启动服务器监听特定端口(8080)
  • 自动打开浏览器并打开特定网址(localhost:8080

说明:express服务器提供静态文件服务,不过它还使用了http-proxy-middleware,一个http请求代理的中间件。前端开发过程中需要使用到后台的API的话,可以通过配置proxyTable来将相应的后台请求代理到专用的API服务器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// 检查NodeJS和npm的版本
require('./check-versions')()

// 获取基本配置
var config = require('../config')
// 如果Node的环境变量中没有设置当前的环境(NODE_ENV),则使用config中的dev环境配置作为当前的环境
if (!process.env.NODE_ENV) {
process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
}

// opn是一个可以调用默认软件打开网址、图片、文件等内容的插件
// 这里用它来调用默认浏览器打开dev-server监听的端口,例如:localhost:8080
var opn = require('opn')
var path = require('path')
var express = require('express')
var webpack = require('webpack')
// http-proxy-middleware是一个express中间件,用于将http请求代理到其他服务器
// 例:localhost:8080/api/xxx --> localhost:3000/api/xxx
// 这里使用该插件可以将前端开发中涉及到的请求代理到提供服务的后台服务器上,方便与服务器对接
var proxyMiddleware = require('http-proxy-middleware')
// 开发环境下的webpack配置
var webpackConfig = require('./webpack.dev.conf')

// dev-server 监听的端口,如果没有在命令行传入端口号,则使用config.dev.port设置的端口,例如8080
var port = process.env.PORT || config.dev.port
// 用于判断是否要自动打开浏览器的布尔变量,当配置文件中没有设置自动打开浏览器的时候其值为 false
var autoOpenBrowser = !!config.dev.autoOpenBrowser
// HTTP代理表,指定规则,将某些API请求代理到相应的服务器
var proxyTable = config.dev.proxyTable
// 创建express服务器
var app = express()
// webpack根据配置开始编译打包源码并返回compiler对象
var compiler = webpack(webpackConfig)
// webpack-dev-middleware将webpack编译打包后得到的产品文件存放在内存中而没有写进磁盘
// 将这个中间件挂到express上使用之后即可提供这些编译后的产品文件服务
var devMiddleware = require('webpack-dev-middleware')(compiler, {
publicPath: webpackConfig.output.publicPath, // 设置访问路径为webpack配置中的output里面所对应的路径
quiet: true // 设置为true,使其不要在控制台输出日志
})
// webpack-hot-middleware,用于实现热重载功能的中间件
var hotMiddleware = require('webpack-hot-middleware')(compiler, {
log: false, // 关闭控制台的日志输出
heartbeat: 2000 // 发送心跳包的频率
})
// webpack(重新)编译打包完成后并将js、css等文件inject到html文件之后,通过热重载中间件强制页面刷新
compiler.plugin('compilation', function (compilation) {
compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
hotMiddleware.publish({ action: 'reload' })
cb()
})
})

// 根据 proxyTable 中的代理请求配置来设置express服务器的http代理规则
Object.keys(proxyTable).forEach(function (context) {
var options = proxyTable[context]
// 格式化options,例如将'www.example.com'变成{ target: 'www.example.com' }
if (typeof options === 'string') {
options = { target: options }
}
app.use(proxyMiddleware(options.filter || context, options))
})

// handle fallback for HTML5 history API
// 重定向不存在的URL,用于支持SPA(单页应用)
// 例如使用vue-router并开启了history模式
app.use(require('connect-history-api-fallback')())

// serve webpack bundle output
// 挂载webpack-dev-middleware中间件,提供webpack编译打包后的产品文件服务
app.use(devMiddleware)

// enable hot-reload and state-preserving
// compilation error display
// 挂载热重载中间件
app.use(hotMiddleware)

// serve pure static assets
// 提供static文件夹上的静态文件服务
var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
app.use(staticPath, express.static('./static'))

// 访问链接
var uri = 'http://localhost:' + port

// 创建promise,在应用服务启动之后resolve
// 便于外部文件require了这个dev-server之后的代码编写
var _resolve
var readyPromise = new Promise(resolve => {
_resolve = resolve
})

console.log('> Starting dev server...')
// webpack-dev-middleware等待webpack完成所有编译打包之后输出提示语到控制台,表明服务正式启动
// 服务正式启动才自动打开浏览器进入页面
devMiddleware.waitUntilValid(() => {
console.log('> Listening at ' + uri + '\n')
// when env is testing, don't need open it
if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
opn(uri)
}
_resolve()
})

// 启动express服务器并监听相应的端口
var server = app.listen(port)

// 暴露本模块的功能给外部使用,例如下面这种用法
// var devServer = require('./build/dev-server')
// devServer.ready.then(() => {...})
// if (...) { devServer.close() }
module.exports = {
ready: readyPromise,
close: () => {
server.close()
}
}

webpack.base.conf.js

从代码中看到,dev-server使用的webpack配置来自build/webpack.dev.conf.js文件(测试环境下使用的是build/webpack.prod.conf.js,这里暂时不考虑测试环境)。而build/webpack.dev.conf.js中又引用了webpack.base.conf.js,这里我先分析webpack.base.conf.js

webpack.base.conf.js主要完成了下面这些事情:

  • 配置webpack编译入口
  • 配置webpack输出路径和命名规则
  • 配置模块resolve规则
  • 配置不同类型模块的处理规则

说明:这个配置里面只配置了.js.vue、图片、字体等几类文件的处理规则,如果需要处理其他文件可以在module.rules里面另行配置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
var path = require('path')
var fs = require('fs')
var utils = require('./utils')
var config = require('../config')
var vueLoaderConfig = require('./vue-loader.conf')

// 获取绝对路径
function resolve (dir) {
return path.join(__dirname, '..', dir)
}

module.exports = {
// webpack入口文件
entry: {
app: './src/main.js'
},
// webpack输出路径和命名规则
output: {
// webpack输出的目标文件夹路径(例如:/dist)
path: config.build.assetsRoot,
// webpack输出bundle文件命名格式
filename: '[name].js',
// webpack编译输出的发布路径(例如'//cdn.xxx.com/app/')
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
// 模块resolve的规则
resolve: {
extensions: ['.js', '.vue', '.json'],
// 别名,方便引用模块,例如有了别名之后,
// import Vue from 'vue/dist/vue.common.js'可以写成 import Vue from 'vue'
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
},
symlinks: false
},
// 不同类型模块的处理规则
module: {
rules: [
{// 对src和test文件夹下的.js和.vue文件使用eslint-loader进行代码规范检查
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter')
}
},
{// 对所有.vue文件使用vue-loader进行编译
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{// 对src和test文件夹下的.js文件使用babel-loader将es6+的代码转成es5
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test')]
},
{// 对图片资源文件使用url-loader
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
// 小于10K的图片转成base64编码的dataURL字符串写到代码中
limit: 10000,
// 其他的图片转移到静态资源文件夹
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{// 对多媒体资源文件使用url-loader
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
// 小于10K的资源转成base64编码的dataURL字符串写到代码中
limit: 10000,
// 其他的资源转移到静态资源文件夹
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{// 对字体资源文件使用url-loader
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
// 小于10K的资源转成base64编码的dataURL字符串写到代码中
limit: 10000,
// 其他的资源转移到静态资源文件夹
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
}
}

webpack.dev.conf.js

接下来看webpack.dev.conf.js,这里面在webpack.base.conf的基础上增加完善了开发环境下面的配置,主要包括下面几件事情:

  • 将webpack的热重载客户端代码添加到每个entry对应的应用
  • 合并基础的webpack配置
  • 配置样式文件的处理规则,styleLoaders
  • 配置Source Maps
  • 配置webpack插件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
var utils = require('./utils')
var webpack = require('webpack')
var config = require('../config')
// webpack-merge是一个可以合并数组和对象的插件
var merge = require('webpack-merge')
var baseWebpackConfig = require('./webpack.base.conf')
// html-webpack-plugin用于将webpack编译打包后的产品文件注入到html模板中
// 即自动在index.html里面加上<link>和<script>标签引用webpack打包后的文件
var HtmlWebpackPlugin = require('html-webpack-plugin')
// friendly-errors-webpack-plugin用于更友好地输出webpack的警告、错误等信息
var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')

// add hot-reload related code to entry chunks
// 给每个入口页面(应用)加上dev-client,用于跟dev-server的热重载插件通信,实现热更新
Object.keys(baseWebpackConfig.entry).forEach(function (name) {
baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])
})

module.exports = merge(baseWebpackConfig, {
module: {
// 样式文件的处理规则,对css/sass/scss等不同内容使用相应的styleLoaders
// 由utils配置出各种类型的预处理语言所需要使用的loader,例如sass需要使用sass-loader
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap })
},
// cheap-module-eval-source-map is faster for development
// 使用这种source-map更快
devtool: '#cheap-module-eval-source-map',
// webpack插件
plugins: [
new webpack.DefinePlugin({
'process.env': config.dev.env
}),
// 开启webpack热更新功能
new webpack.HotModuleReplacementPlugin(),
// webpack编译过程中出错的时候跳过报错阶段,不会阻塞编译,在编译结束后报错
new webpack.NoEmitOnErrorsPlugin(),
// 自动将依赖注入html模板,并输出最终的html文件到目标文件夹
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
}),
new FriendlyErrorsPlugin()
]
})

utils

此配置文件是vue开发环境的webpack相关配置文件,主要用来处理css-loadervue-style-loader

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// 引入nodejs路径模块
var path = require('path')
// 引入config目录下的index.js配置文件
var config = require('../config')
// 引入extract-text-webpack-plugin插件,用来将css提取到单独的css文件中
// 详情请看(1)
var ExtractTextPlugin = require('extract-text-webpack-plugin')
// exports其实就是一个对象,用来导出方法的最终还是使用module.exports,此处导出assetsPath
exports.assetsPath = function (_path) {
// 如果是生产环境assetsSubDirectory就是'static',否则还是'static',哈哈哈
var assetsSubDirectory = process.env.NODE_ENV === 'production'
? config.build.assetsSubDirectory
: config.dev.assetsSubDirectory
// path.join和path.posix.join的区别就是,前者返回的是完整的路径,后者返回的是完整路径的相对根路径
// 也就是说path.join的路径是C:a/a/b/xiangmu/b,那么path.posix.join就是b
return path.posix.join(assetsSubDirectory, _path)
// 所以这个方法的作用就是返回一个干净的相对根路径
}

// 下面是导出cssLoaders的相关配置
exports.cssLoaders = function (options) {
// options如果没值就是空对象
options = options || {}
// cssLoader的基本配置
var cssLoader = {
loader: 'css-loader',
options: {
// options是用来传递参数给loader的
// minimize表示压缩,如果是生产环境就压缩css代码
minimize: process.env.NODE_ENV === 'production',
// 是否开启cssmap,默认是false
sourceMap: options.sourceMap
}
}

// generate loader string to be used with extract text plugin
function generateLoaders (loader, loaderOptions) {
// 将上面的基础cssLoader配置放在一个数组里面
var loaders = [cssLoader]
// 如果该函数传递了单独的loader就加到这个loaders数组里面,这个loader可能是less,sass之类的
if (loader) {
loaders.push({
// 加载对应的loader
loader: loader + '-loader',
// Object.assign是es6的方法,主要用来合并对象的,浅拷贝
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}

// Extract CSS when that option is specified
// (which is the case during production build)
// 注意这个extract是自定义的属性,可以定义在options里面,主要作用就是当配置为true就把文件单独提取,false表示不单独提取,这个可以在使用的时候单独配置,瞬间觉得vue作者好牛逼
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader'
})
} else {
return ['vue-style-loader'].concat(loaders)
}
// 上面这段代码就是用来返回最终读取和导入loader,来处理对应类型的文件
}

// https://vue-loader.vuejs.org/en/configurations/extract-css.html
return {
css: generateLoaders(), // css对应 vue-style-loader 和 css-loader
postcss: generateLoaders(), // postcss对应 vue-style-loader 和 css-loader
less: generateLoaders('less'), // less对应 vue-style-loader 和 less-loader
sass: generateLoaders('sass', { indentedSyntax: true }), // sass对应 vue-style-loader 和 sass-loader
scss: generateLoaders('sass'), // scss对应 vue-style-loader 和 sass-loader
stylus: generateLoaders('stylus'), // stylus对应 vue-style-loader 和 stylus-loader
styl: generateLoaders('stylus') // styl对应 vue-style-loader 和 styl-loader
}
}

// Generate loaders for standalone style files (outside of .vue)
// 下面这个主要处理import这种方式导入的文件类型的打包,上面的exports.cssLoaders是为这一步服务的
exports.styleLoaders = function (options) {
var output = []
// 下面就是生成的各种css文件的loader对象
var loaders = exports.cssLoaders(options)
for (var extension in loaders) {
// 把每一种文件的laoder都提取出来
var loader = loaders[extension]
output.push({
// 把最终的结果都push到output数组中,大事搞定
test: new RegExp('\\.' + extension + '$'),
use: loader
})
}
return output
}

vue-loader.conf.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var utils = require('./utils')
var config = require('../config')
var isProduction = process.env.NODE_ENV === 'production'

module.exports = {
// 处理.vue文件中的样式
loaders: utils.cssLoaders({
// 是否打开source-map
sourceMap: isProduction
? config.build.productionSourceMap
: config.dev.cssSourceMap,
// 是否提取样式到单独的文件
extract: isProduction
}),
transformToRequire: {
video: 'src',
source: 'src',
img: 'src',
image: 'xlink:href'
}
}

dev-client.js

dev-client.js里面主要写了浏览器端代码,用于实现webpack的热更新。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/* eslint-disable */
// 实现浏览器端的EventSource,用于跟服务器双向通信
// webpack热重载客户端跟dev-server上的热重载插件之间需要进行双向通信
// 服务端webpack重新编译后,会向客户端推送信息,告诉客户端进行更新
require('eventsource-polyfill')
// webpack热重载客户端
var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')

// 客户端收到更新动作,执行页面刷新
hotClient.subscribe(function (event) {
if (event.action === 'reload') {
window.location.reload()
}
})

build.js

执行npm run build的时候首先执行的是build/build.js文件,build.js主要完成下面几件事:

  • loading动画
  • 删除目标文件夹
  • 执行webpack构建
  • 输出信息

说明:webpack编译之后会输出到配置里面指定的目标文件夹;删除目标文件夹之后再创建是为了去除旧的内容,以免产生不可预测的影响。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// 检查NodeJS和npm的版本
require('./check-versions')()

process.env.NODE_ENV = 'production'

// ora,一个可以在终端显示spinner的插件
var ora = require('ora')
// rm,用于删除文件或文件夹的插件
var rm = require('rimraf')
var path = require('path')
// chalk,用于在控制台输出带颜色字体的插件
var chalk = require('chalk')
var webpack = require('webpack')
var config = require('../config')
var webpackConfig = require('./webpack.prod.conf')

var spinner = ora('building for production...')
spinner.start() // 开启loading动画

// 首先将整个dist文件夹以及里面的内容删除,以免遗留旧的没用的文件
// 删除完成后才开始webpack构建打包
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
if (err) throw err
// 执行webpack构建打包,完成之后在终端输出构建完成的相关信息或者输出报错信息并退出程序
webpack(webpackConfig, function (err, stats) {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false,
chunks: false,
chunkModules: false
}) + '\n\n')

if (stats.hasErrors()) {
console.log(chalk.red(' Build failed with errors.\n'))
process.exit(1)
}

console.log(chalk.cyan(' Build complete.\n'))
console.log(chalk.yellow(
' Tip: built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n'
))
})
})

check-versions.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// chalk, 用于在控制台输出带颜色字体的插件
var chalk = require('chalk')
// semver, 语义化版本检查插件(The semantic version parser used by npm)
var semver = require('semver')
var packageConfig = require('../package.json')
// shelljs, 执行Unix命令行的插件
var shell = require('shelljs')
// 开辟子进程执行指令cmd并返回结果
function exec (cmd) {
return require('child_process').execSync(cmd).toString().trim()
}

// node和npm版本需求
var versionRequirements = [
{
name: 'node',
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)
}
}

config目录

index.js

config文件夹下最主要的文件就是index.js了,在这里面描述了开发和构建两种环境下的配置,前面的build文件夹下也有不少文件引用了index.js里面的配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
// see http://vuejs-templates.github.io/webpack for documentation.
var path = require('path')

module.exports = {
// 构建产品时使用的配置
build: {
// 环境变量
env: require('./prod.env'),
// html入口文件
index: path.resolve(__dirname, '../dist/index.html'),
// 产品文件的存放路径
assetsRoot: path.resolve(__dirname, '../dist'),
// 二级目录,存放静态资源文件的目录,位于dist文件夹下
assetsSubDirectory: 'static',
// 发布路径,如果构建后的产品文件有用于发布CDN或者放到其他域名的服务器,可以在这里进行设置
// 设置之后构建的产品文件在注入到index.html中的时候就会带上这里的发布路径
assetsPublicPath: '/',
// 是否使用source-map
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
// 是否开启gzip压缩
productionGzip: false,
// gzip模式下需要压缩的文件的扩展名,设置js、css之后就只会对js和css文件进行压缩
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
// 是否展示webpack构建打包之后的分析报告
bundleAnalyzerReport: process.env.npm_config_report
},
// 开发过程中使用的配置
dev: {
// 环境变量
env: require('./dev.env'),
// dev-server监听的端口
port: 8080,
// 是否自动打开浏览器
autoOpenBrowser: true,
// 静态资源文件夹
assetsSubDirectory: 'static',
// 发布路径
assetsPublicPath: '/',
// 代理配置表,在这里可以配置特定的请求代理到对应的API接口
// 例如将'localhost:8080/api/xxx'代理到'www.example.com/api/xxx'
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
cssSourceMap: false
}
}

prod.env.js

当开发是调取dev.env.js的开发环境配置,发布时调用prod.env.js的生产环境配置。

1
2
3
4
'use strict'
module.exports = {
NODE_ENV: '"production"'
}

dev.env.js

1
2
3
4
5
6
7
8
'use strict'//采用严格模式
const merge = require('webpack-merge')//①
const prodEnv = require('./prod.env')
//webpack-merge提供了一个合并函数,它将数组和合并对象创建一个新对象。
//如果遇到函数,它将执行它们,通过算法运行结果,然后再次将返回的值封装在函数中.这边将dev和prod进行合并
module.exports = merge(prodEnv, {
NODE_ENV: '"development"'
})

static目录

这个目录是你不想通过webpack处理的静态资源目录。这些目录中的资源会在webpack构建的时候,被直接复制到相同的目录中。

src目录

这个是你放绝大部分程序代码的地方。如何管理这个目录内的所有内容随你决定。

.babelrc

Babel解释器的配置文件,存放在根目录下。Babel是一个转码器,项目里需要用它将ES6代码转为ES5代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
//设定转码规则
"presets": [
["env", { "modules": false }],
"stage-2"
],
//转码用的插件
"plugins": ["transform-runtime"],
"comments": false,
//对BABEL_ENV或者NODE_ENV指定的不同的环境变量,进行不同的编译操作
"env": {
"test": {
"presets": ["env", "stage-2"],
"plugins": [ "istanbul" ]
}
}
}

.editorconfig

该文件定义项目的编码规范,编译器的行为会与.editorconfig文件中定义的一致,并且其优先级比编译器自身的设置要高,这在多人合作开发项目时十分有用而且必要。

1
2
3
4
5
6
7
8
9
root = true

[*] // 对所有文件应用下面的规则
charset = utf-8 // 编码规则用utf-8
indent_style = space // 缩进用空格
indent_size = 2 // 缩进数量为2个空格
end_of_line = lf // 换行符格式
insert_final_newline = true // 是否在文件的最后插入一个空行
trim_trailing_whitespace = true // 是否删除行尾的空格

.postcessrc.js

.postcssrc.js文件其实是postcss-loader包的一个配置,在webpack的旧版本可以直接在webpack.config.js中配置,现版本中postcss的文档示例独立出.postcssrc.js,里面写进去需要使用到的插件

1
2
3
4
5
6
7
module.exports = {
"plugins": {
"postcss-import": {},//①
"postcss-url": {},//②
"autoprefixer": {}//③
}
}

package.json

package.json文件是项目根目录下的一个文件,定义该项目开发所需要的各种模块以及一些项目配置信息(如项目名称、版本、描述、作者等)。

scripts字段

这个字段定义了你可以用npm运行的命令。在开发环境下,在命令行工具中运行npm run dev就相当于执行 node build/dev-server.js。也就是开启了一个node写的开发行建议服务器。由此可以看出script字段是用来指定npm相关命令的缩写。

1
2
3
4
"scripts": {
"dev": "node build/dev-server.js",
"build": "node build/build.js"
},

dependencies字段和devDependencies字段

  • dependencies字段指项目运行时所依赖的模块;
  • devDependencies字段指定了项目开发时所依赖的模块;

在命令行中运行npm install命令,会自动安装dependencies和devDempendencies字段中的模块。

下面是一个package.json例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
{
//从name到private都是package的配置信息,也就是我们在脚手架搭建中输入的项目描述
"name": "shop",//项目名称:不能以.(点)或者_(下划线)开头,不能包含大写字母,具有明确的的含义与现有项目名字不重复
"version": "1.0.0",//项目版本号:遵循“大版本.次要版本.小版本”
"description": "A Vue.js project",//项目描述
"author": "qietuniu",//作者名字
"private": true,//是否私有
//scripts中的子项即是我们在控制台运行的脚本的缩写
"scripts": {
//①webpack-dev-server:启动了http服务器,实现实时编译;
//inline模式会在webpack.config.js入口配置中新增webpack-dev-server/client?http://localhost:8080/的入口,使得我们访问路径为localhost:8080/index.html(相应的还有另外一种模式Iframe);
//progress:显示打包的进度
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",//与npm run dev相同,直接运行开发环境
"build": "node build/build.js"//使用node运行build文件
},
//②dependencies(项目依赖库):在安装时使用--save则写入到dependencies
"dependencies": {
"vue": "^2.5.2",//vue.js
"vue-router": "^3.0.1"//vue的路由插件
},
//和devDependencies(开发依赖库):在安装时使用--save-dev将写入到devDependencies
"devDependencies": {
"autoprefixer": "^7.1.2",//autoprefixer作为postcss插件用来解析CSS补充前缀,例如 display: flex会补充为display:-webkit-box;display: -webkit-flex;display: -ms-flexbox;display: flex。
//babel:以下几个babel开头的都是针对es6解析的插件。用最新标准编写的 JavaScript 代码向下编译成可以在今天随处可用的版本
"babel-core": "^6.22.1",//babel的核心,把 js 代码分析成 ast ,方便各个插件分析语法进行相应的处理。
"babel-helper-vue-jsx-merge-props": "^2.0.3",//预制babel-template函数,提供给vue,jsx等使用
"babel-loader": "^7.1.1",//使项目运行使用Babel和webpack来传输js文件,使用babel-core提供的api进行转译
"babel-plugin-syntax-jsx": "^6.18.0",//支持jsx
"babel-plugin-transform-runtime": "^6.22.0",//避免编译输出中的重复,直接编译到build环境中
"babel-plugin-transform-vue-jsx": "^3.5.0",//babel转译过程中使用到的插件,避免重复
"babel-preset-env": "^1.3.2",//转为es5,transform阶段使用到的插件之一
"babel-preset-stage-2": "^6.22.0",//ECMAScript第二阶段的规范
"chalk": "^2.0.1",//用来在命令行输出不同颜色文字
"copy-webpack-plugin": "^4.0.1",//拷贝资源和文件
"css-loader": "^0.28.0",//webpack先用css-loader加载器去解析后缀为css的文件,再使用style-loader生成一个内容为最终解析完的css代码的style标签,放到head标签里
"extract-text-webpack-plugin": "^3.0.0",//将一个以上的包里面的文本提取到单独文件中
"file-loader": "^1.1.4",//③打包压缩文件,与url-loader用法类似
"friendly-errors-webpack-plugin": "^1.6.1",//识别某些类别的WebPACK错误和清理,聚合和优先排序,以提供更好的开发经验
"html-webpack-plugin": "^2.30.1",//简化了HTML文件的创建,引入了外部资源,创建html的入口文件,可通过此项进行多页面的配置
"node-notifier": "^5.1.2",//支持使用node发送跨平台的本地通知
"optimize-css-assets-webpack-plugin": "^3.2.0",//压缩提取出的css,并解决ExtractTextPlugin分离出的js重复问题(多个文件引入同一css文件)
"ora": "^1.2.0",//加载(loading)的插件
"portfinder": "^1.0.13",//查看进程端口
"postcss-import": "^11.0.0",//可以消耗本地文件、节点模块或web_modules
"postcss-loader": "^2.0.8",//用来兼容css的插件
"postcss-url": "^7.2.1",//URL上重新定位、内联或复制
"rimraf": "^2.6.0",//节点的UNIX命令RM—RF,强制删除文件或者目录的命令
"semver": "^5.3.0",//用来对特定的版本号做判断的
"shelljs": "^0.7.6",//使用它来消除shell脚本在UNIX上的依赖性,同时仍然保留其熟悉和强大的命令,即可执行Unix系统命令
"uglifyjs-webpack-plugin": "^1.1.1",//压缩js文件
"url-loader": "^0.5.8",//压缩文件,可将图片转化为base64
"vue-loader": "^13.3.0",//VUE单文件组件的WebPACK加载器
"vue-style-loader": "^3.0.1",//类似于样式加载程序,您可以在CSS加载器之后将其链接,以将CSS动态地注入到文档中作为样式标签
"vue-template-compiler": "^2.5.2",//这个包可以用来预编译VUE模板到渲染函数,以避免运行时编译开销和CSP限制
"webpack": "^3.6.0",//打包工具
"webpack-bundle-analyzer": "^2.9.0",//可视化webpack输出文件的大小
"webpack-dev-server": "^2.9.1",//提供一个提供实时重载的开发服务器
"webpack-merge": "^4.1.0"//它将数组和合并对象创建一个新对象。如果遇到函数,它将执行它们,通过算法运行结果,然后再次将返回的值封装在函数中
},
//engines是引擎,指定node和npm版本
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
},
//限制了浏览器或者客户端需要什么版本才可运行
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}

参考


----------- 本文结束啦感谢您阅读 -----------

赞赏一杯咖啡

欢迎关注我的其它发布渠道