Skip to content

Instantly share code, notes, and snippets.

@llccing
Created December 14, 2017 07:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save llccing/cd774c8752bf4dd065b3f8b91d85df77 to your computer and use it in GitHub Desktop.
Save llccing/cd774c8752bf4dd065b3f8b91d85df77 to your computer and use it in GitHub Desktop.

idcui项目说明

技术栈: Vue + iview

目录结构介绍

|-- build                            	// webpack配置文件
|-- config                           	// 项目打包路径
|-- dist                             	// 打包输出目录
|-- node_modules                     	// 项目依赖目录
|-- src                              	// 源码目录
|-- |-- assets                       	// 模块资源(由webapck进行处理)
|       |-- img                      
|       |-- json                     	// 接口模拟数据
|       |-- lib                      	// 插件
|       |-- style                    	// 公共样式  
|           |-- theme                	// 主题    
|   |-- components                   	// 组件
|       |-- Header.vue               	// 公共头部
|   |-- store                        	// vuex,全局状态
|		|-- views                   	   	// 主要路由页面
|       |-- index.vue                	// 首页
|   |-- App.vue                      	// 页面入口文件
|   |-- main.js                      	// 程序入口文件,加载各种公共组件
|-- static                           	// 纯静态资源(直接拷贝)
|-- .babelrc                         	// ES6语法编译配置
|-- .editorconfig                    	// 代码编写规格
|-- .eslintignore                    	// eslint忽略文件
|-- .eslinttrc.js                    	// eslint检查文件
|-- .gitignore                       	// 忽略的文件
|-- .postcssrc.js                    	// postcss配置文件
|-- index.html                       	// 入口html文件
|-- package.json                     	// 项目及工具的依赖配置文件
|-- README.md                        	// 说明

配置文件说明

|-- build                             // 构建文件
|   |-- build.js											//  
|   |-- check-versions.js							//
|   |-- dev-client.js  
|   |-- dev-server.js
|   |-- utils.js
|   |-- vue-loader.config.js
|   |-- webapck.base.conf.js
|   |-- webpack.dev.conf.js
|   |-- webpack.prod.conf.js
|   |-- webpack.test.conf.js
|-- config
|   |-- dev.env.js
|   |-- index.js
|   |-- prod.env.js
|-- package.json
|   |-- test.env.js

package.json

开发时我们常用的命令为 npm run devnpm run build, 那么我们就从这两个命令入手。 这两行命令对应执行的是package.json文件中的script属性对应的命令。

"scripts": {
    "dev": "node build/dev-server.js",
    "start": "node build/dev-server.js",
    "build": "node build/build.js",
    "unit": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run",
    "e2e": "node test/e2e/runner.js",
    "test": "npm run unit && npm run e2e",
    "lint": "eslint --ext .js,.vue src test/unit/specs test/e2e/specs"
  },

由此可见,在我们执行npm run dev/start实际上是node在执行build下的dev-server.js

dev-server.js

主要做的内容

  1. 检查node和npm版本
  2. 引入插件和配置
  3. 创建express服务器和webpack编译器
  4. 配置开发中间件(webpack-dev-middleware)和热重载中间件(wwebpack-hot-middleware)
  5. 挂载大力服务和中间件
  6. 配置静态资源
  7. 启动服务器并监听特定端口
  8. 自定打开浏览器,进入特定网址

说明:

express服务器提供静态文件服务,和一个http请求代理的中间件。前端开发需要请求后端api的话,可配置proxyTable来将相应的请求代理到专用api服务器。

详细:

// 检查版本
require('./check-versions')()

// 读取配置文件
var config = require('../config')
/**
* 如果不能判断当前环境为dev/production环境,则将环境设置为开发环境
* process对象是Node的一个全局对象,提供当前Node进程的信息。
* process.env返回一个对象,成员为当前Shell的环境变量,如process.env.HOME返回用户主目录
* NODE_ENV是自定义的环境变量,用来确定所处的开发阶段development/production/testing
**/
if (!process.env.NODE_ENV) {
  // 读取dev的config文件,将dev.env.NODE_ENV作为当前环境
  process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
}

// 一个更好跨平台node-open,可以打开网站,文件、可执行文件
var opn = require('opn')
// nodejs的路径模块,用于路径处理
var path = require('path')
// 快速、包容、简约的nodejsweb框架,这里主要用于开发环境的调试
var express = require('express')
// 一个现代JavaScript应用程序的模块打包器
var webpack = require('webpack')
// Node.js的代理中间件,兼容Node.js服务器,轻松实现代理
var proxyMiddleware = require('http-proxy-middleware')
// 如果是测试或者生产环境,则使用webpack的生产环境配置,否则使用webpack的开发环境配置
var webpackConfig = (process.env.NODE_ENV === 'testing' || process.env.NODE_ENV === 'production')
  ? require('./webpack.prod.conf')
  : require('./webpack.dev.conf')

// 开发服务器对于入站流量监听的默认端口号,如果没有自定义端口,则使用开发配置的端口
var port = process.env.PORT || config.dev.port

// 自动打开浏览器,!!表示强制类型转换为Boolean,这里用来判断属性是否存在, !!null/!!undefined/!!""=>false
var autoOpenBrowser = !!config.dev.autoOpenBrowser

// 配置http代理到自定义的api后端
// https://github.com/chimurai/http-proxy-middleware
var proxyTable = config.dev.proxyTable

// 使用express启动一个服务
var app = express()

// 启动webpack进行编译
var compiler = webpack(webpackConfig)

/**
* 启动webpack-dev-middleware,将编译的文件暂存到内存中
* ? webpack-dev-middleware:在开发环境中即时刷新,建议仅在开发中使用
**/
var devMiddleware = require('webpack-dev-middleware')(compiler, {
  // 打包文件将能够在浏览器的这个目录下找到
  publicPath: webpackConfig.output.publicPath,
  // 设置为true时,控制台(console)不会输出任何启动信息,并且webpack的错误、警告不可见
  quiet: true
})
/**
* 启动webpack-hot-middleware,热加载。
**/
var hotMiddleware = require('webpack-hot-middleware')(compiler, {
  // 输出日志,默认是以console.log()的形式
  log: false,
  // 为了保持连接而向客户端发送心跳更新的间隔时间,通常为客户端超时时间的一半
  heartbeat: 2000
})

/*
* 当html-webpack-plugin模板改变时,强制页面重载
* html-webpack-plugin: 为了服务webpack的包而简化html文件创建的插件
**/
compiler.plugin('compilation', function (compilation) {
  // html-webpack-plugin-after-emit, 模板改变后的异步事件
  compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
    hotMiddleware.publish({ action: 'reload' })
    cb()
  })
})

// 代理api请求,将proxyTable中的代理配置挂载到启动的express服务上
Object.keys(proxyTable).forEach(function (context) {
  var options = proxyTable[context]
  if (typeof options === 'string') {
    options = { target: options }
  }
  // 使用代理中间件
  app.use(proxyMiddleware(options.filter || context, options))
})


// 处理HTML5 history api的回退
// 使用 connect-history-api-fallback匹配资源,若不匹配则重新定向到指定地址
app.use(require('connect-history-api-fallback')())


// 将暂存在内存中的webpack编译后的文件挂载到express服务上
app.use(devMiddleware)

// 使热加载和状态保留生效
// 显示编译错误
// 将热加载挂载到express服务上
app.use(hotMiddleware)

// 拼接static文件夹的静态资源路径
// posix(Portable Operating System Interface)可移植操作系统接口
var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
// 为静态资源提供响应服务
app.use(staticPath, express.static('./static'))

// 应用的地址信息
var uri = 'http://localhost:' + port

// Promise对象,异步操作,好处是将异步操作以同步操作的流程表达出来,避免层层嵌套的回调函数。
var _resolve
var readyPromise = new Promise(resolve => {
  _resolve = resolve
})

console.log('> Starting dev server...')
// 当打包文件生成,或者重新生成后,执行的回调函数
devMiddleware.waitUntilValid(() => {
  console.log('> Listening at ' + uri + '\n')
  // when env is testing, don't need open it
  // 当开发环境不是'testing'时,自动打开浏览器
  if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') {
    opn(uri)
  }
  // 异步执行完成?
  _resolve()
})
// 启动express服务器并监听port端口
var server = app.listen(port)

module.exports = {
  ready: readyPromise,
  close: () => {
    server.close()
  }
}

webpack.base.conf.js

内容:

  1. 配置webpack编译入口,entry
  2. 配置webpack输出路径和命名规则
  3. 配置模块resolve规则
  4. 配置不同类型的模块的处理规则

说明:

这个配置中配置了js/vue/媒体/图片/字体等几类文件的处理规则,如果想处理其他文件可以在module.rules中配置

详细:

// Node.js path模块
var path = require('path')
// 自定义工具方法
var utils = require('./utils')
// 配置
var config = require('../config')
// vue-loader的配置项
var vueLoaderConfig = require('./vue-loader.conf')

function resolve (dir) {
  return path.join(__dirname, '..', dir)
}

module.exports = {
  // 编译入口
  entry: {
    app: './src/main.js'
  },
  // 输出出口
  output: {
    // 一个绝对路径,/dist
    path: config.build.assetsRoot,
    // 每个输出bundle的名称,输出到output.path指定的目录下
    filename: '[name].js',
    // 对于按需加载(on-demand-load)或加载外部资源(external resource)(如图片、文件等),output.publicPath是个重要选项,如果指定错误会出现404。
    publicPath: process.env.NODE_ENV === 'production'
      ? config.build.assetsPublicPath
      : config.dev.assetsPublicPath
  },
  // 配置模块如何解析
  resolve: {
    // 自动解析确定的扩展,使用户引入时可以不带扩展
    extensions: ['.js', '.vue', '.json'],
    // 创建import或者require的别名,来确保引入模块变得简单
    alias: {
      // 在给定的件键后的末尾添加$,表示精准匹配
      // 所以 import Vue from 'vue/dist/vue.esm.js' = import Vue from 'vue'
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),
    }
  },
  // 配置项目中不同模块的处理方式
  module: {
    // 创建模块时,匹配请求的规则数组。这些规则能够修改模块的创建方式,能够对模块应用loader,或者修改解析器(parser)。
    rules: [
      // 对src和test文件夹下的js/vue文件使用eslint-loader
      {
        // Rule.resource.test的简写,规则匹配
        test: /\.(js|vue)$/,
        // eslint是一个用来识别ECMAScript并且按照规则给出报告的代码检测工具,使用它可以避免低级错误和统一代码的风格。
        loader: 'eslint-loader',
        // 指定loader的种类(pre/inline/normal/post)(!,-!,!!)
        enforce: 'pre',
        // 在规则中,属性test/include/exclude/resource对resource匹配,当有多个条件时,都匹配。
        include: [resolve('src'), resolve('test')],
        // options可以为字符串或者对象,传递到loader中,为loader的选项
        options: {
          formatter: require('eslint-friendly-formatter')
        }
      },
      // 对vue文件使用vue-loader
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: vueLoaderConfig
      },
      // 对js文件使用babel-loader
      {
        test: /\.js$/,
        loader: 'babel-loader',
        include: [resolve('src'), resolve('test')]
      },
      // 对图片资源文件使用url-loader,options.name指明了输出的命名规则
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          // 图片当大小不超过limit设置的大小时,转为Data URL
          limit: 10000,
          name: utils.assetsPath('img/[name].[hash:7].[ext]')
        }
      },
      // 媒体资源文件
      {
        test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('media/[name].[hash:7].[ext]')
        }
      },
      // 字体资源文件
      {
        test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          limit: 10000,
          name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
        }
      }
    ]
  }
}

webpack.dev.conf.js

内容:

  1. 将热重载的配置添加到entry chunks
  2. 合并基础的webpack配置
  3. 使用styleLoaders
  4. 配置source Maps
  5. 配置webpack插件

详细:

// 工具函数
var utils = require('./utils')
// webpack
var webpack = require('webpack')
// 配置文件
var config = require('../config')
// 一个可以合并数组和对象的插件
var merge = require('webpack-merge')
// webpack编译基本配置
var baseWebpackConfig = require('./webpack.base.conf')

// 一个用于生成HTML文件并自动注入依赖文件(link/script)的webpack插件
var HtmlWebpackPlugin = require('html-webpack-plugin')

// 错误提示插件
var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')

// add hot-reload related code to entry chunks
// 给webpack入口文件配置热重载
Object.keys(baseWebpackConfig.entry).forEach(function (name) {
  baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name])
})

// 合并基础的webpack配置
module.exports = merge(baseWebpackConfig, {
  // 配置样式文件的处理规则
  module: {
    rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap })
  },

  // 配置source-map,在开发中使用cheap-module-eval-source-map更快
  devtool: '#cheap-module-eval-source-map',

  // 配置webpack插件
  plugins: [
    // 定义全局变量的插件,webpack打包时会对变量做替换。
    new webpack.DefinePlugin({
      'process.env': config.dev.env
    }),
    // 热替换插件,不要在生产环境中使用
    // https://github.com/glenjamin/webpack-hot-middleware#installation--usage
    new webpack.HotModuleReplacementPlugin(),
    // 在编译出错时,使用NoEmitOnErrorsPlugin来跳过输出阶段,这样可以确保输出资源不会包含错误
    new webpack.NoEmitOnErrorsPlugin(),
    // 一个生成HTML文件并自动注入依赖(script/link)的插件
    // https://github.com/ampedandwired/html-webpack-plugin
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'index.html',
      inject: true
    }),
    // 有好的错误提示插件
    new FriendlyErrorsPlugin()
  ]
})

utils.js、vue-loader.conf.js

主要内容:

  • utils.js
    1. 配置静态资源路径
    2. 生成cssLoaders用于加载vue文件中的样式
    3. 生成styleLoaders用于加载不再vue文件中的单独存在的样式文件
  • vue-loader.cof.js
    1. 配置了css加载器

详细

vue-loader.conf.js

// 工具库
var utils = require('./utils')
// 配置文件
var config = require('../config')
// 判断是否为生产环境
var isProduction = process.env.NODE_ENV === 'production'

module.exports = {
  // css加载器,开发环境执行,utils.cssLoaders({sourceMap:false,extract: false}),正式环境执行utils.cssLoaders({sourceMap:true,extract: true})

  loaders: utils.cssLoaders({
    sourceMap: isProduction
      ? config.build.productionSourceMap
      : config.dev.cssSourceMap,
    extract: isProduction
  }),
  // 可以将路径直接赋给组件,不用提前require之后再传给组件。
  transformToRequire: {
    video: 'src',
    source: 'src',
    img: 'src',
    image: 'xlink:href'
  }
}

build.js

内容:

  1. loading动画
  2. 删除创建目标文件夹static
  3. webpack编译
  4. 输出信息

说明

删除目标文件夹之后再将webpack编译的内容输出到指定文件夹下。

详细

// 版本检查
require('./check-versions')()

// 改变shell环境变量为生产 "production"
process.env.NODE_ENV = 'production'

// 实现Node.js命令行的loading效果,显示各种状态的图标
var ora = require('ora')
// A `rm -rf` util for nodejs
var rm = require('rimraf')
// Node.js 路径模块
var path = require('path')
// 彩色命令行插件
var chalk = require('chalk')
// webpack
var webpack = require('webpack')
// 项目配置文件
var config = require('../config')
// webpack生产环境配置
var webpackConfig = require('./webpack.prod.conf')

var spinner = ora('building for production...')
spinner.start()
// 清空 /dist/static文件夹下的内容
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
  if (err) throw err
  webpack(webpackConfig, function (err, stats) {
    spinner.stop()
    if (err) throw err
    // process.stdout标准输出对象
    // process.stdout.write等同于console.log()
    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'
    ))
  })
})

webpack.prod.conf.js

内容:

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

详细:

// Node.js模块
var path = require('path')
// 工具函数
var utils = require('./utils')
// webapck
var webpack = require('webpack')
// 配置
var config = require('../config')
// 用于合并对象、数组
var merge = require('webpack-merge')
// 基本的webpack编译配置
var baseWebpackConfig = require('./webpack.base.conf')
// 用于文件、文件夹复制
var CopyWebpackPlugin = require('copy-webpack-plugin')
// 生成HTML并将依赖自动注入文件中
var HtmlWebpackPlugin = require('html-webpack-plugin')
// 用于提取入口chunk中引用的css到独立的css文件中,以并行加载,提升速度。
var ExtractTextPlugin = require('extract-text-webpack-plugin')
// CSS优化,内部使用cssnano来优化css,cssnano内部调用postcss。可以分别了解下。
var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')

// 判断是测试环境是还是生产环境
var env = process.env.NODE_ENV === 'testing'
  ? require('../config/test.env')
  : config.build.env

// 合并webpack基础配置
var webpackConfig = merge(baseWebpackConfig, {
  module: {
    rules: utils.styleLoaders({
      sourceMap: config.build.productionSourceMap,
      extract: true
    })
  },
  // 配置source-map
  devtool: config.build.productionSourceMap ? '#source-map' : false,
  // 配置输出
  output: {
    // 编译输出目录
    path: config.build.assetsRoot,
    // 编译输出的文件名格式
    filename: utils.assetsPath('js/[name].[chunkhash].js'),
    // 没有指定输出名的文件,输出的文件名格式
    chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
  },
  // 配置webpack插件
  plugins: [
    // 定义全局变量的插件,webpack打包时,会对变量做替换
    // http://vuejs.github.io/vue-loader/en/workflow/production.html
    new webpack.DefinePlugin({
      'process.env': env
    }),
    // 丑化压缩代码
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      },
      sourceMap: true
    }),
    // 提取组件中的CSS到单独的文件中
    new ExtractTextPlugin({
      filename: utils.assetsPath('css/[name].[contenthash].css')
    }),

    // 压缩提取的CSS,将不同组件中重复的CSS去除
    new OptimizeCSSPlugin({
      cssProcessorOptions: {
        safe: true
      }
    }),
    // 为了解决缓存问题,使用正确的资源哈希码生成dist/index.html文件
    // 你可以通过编辑index.html文件自定义输出
    // see https://github.com/ampedandwired/html-webpack-plugin
    new HtmlWebpackPlugin({
      filename: process.env.NODE_ENV === 'testing'
        ? 'index.html'
        : config.build.index,
      template: 'index.html',
      // 自动注入js引用到index.html文件的body标签底部
      inject: true,
      minify: {
        // 移除注释
        removeComments: true,
        // 移除空格
        collapseWhitespace: true,
        // 尽可能删除属性的引号,删除可能有点问题
        removeAttributeQuotes: true
        // 更多配置项,可以在以下链接了解
        // https://github.com/kangax/html-minifier#options-quick-reference
      },

      // necessary to consistently work with multiple chunks via CommonsChunkPlugin
      // 尽可能多的使用 CommonsChunkPlugin 来工作 (说啥呢)
      chunksSortMode: 'dependency'
    }),

    // keep module.id stable when vender modules does not change
    // 当vender(第三方库)模块没有变化时,应该让module.id保持稳定
    new webpack.HashedModuleIdsPlugin(),

    // split vendor js into its own file
    // 拆分第三方库
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: function (module, count) {
        // any required modules inside node_modules are extracted to vendor
        // 任何在node_modules中的模块将被提取到第三方库中
        return (
          module.resource &&
          /\.js$/.test(module.resource) &&
          module.resource.indexOf(
            path.join(__dirname, '../node_modules')
          ) === 0
        )
      }
    }),

    // extract webpack runtime and module manifest to its own file in order to
    // prevent vendor hash from being updated whenever app bundle is updated
    // 提取webpack运行时和模块清单提取到自己的文件中,防止当app打包文件更新时第三方库的hash也改变,减少编译时间
    new webpack.optimize.CommonsChunkPlugin({
      name: 'manifest',
      chunks: ['vendor']
    }),
    // 复制自定义静态文件
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, '../static'),
        to: config.build.assetsSubDirectory,
        ignore: ['.*']
      }
    ])
  ]
})

// 判断是否开启了Gzip,若开启则要引入compression插件
if (config.build.productionGzip) {
  var CompressionWebpackPlugin = require('compression-webpack-plugin')

  webpackConfig.plugins.push(
    new CompressionWebpackPlugin({
      asset: '[path].gz[query]',
      algorithm: 'gzip',
      test: new RegExp(
        '\\.(' +
        config.build.productionGzipExtensions.join('|') +
        ')$'
      ),
      threshold: 10240,
      minRatio: 0.8
    })
  )
}

// 在打包时分析生成js的库的构成情况,大小,方便我们做出调整。
if (config.build.bundleAnalyzerReport) {
  var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}

module.exports = webpackConfig

webpack.test.conf.js

说明:

1.引入配置信息

详细:

// 测试单元的webpack编译配置

// 工具函数
var utils = require('./utils')
// webpack
var webpack = require('webpack')
// 合并对象、数组
var merge = require('webpack-merge')
// 基本webpack配置
var baseConfig = require('./webpack.base.conf')

// 合并配置
var webpackConfig = merge(baseConfig, {
  // use inline sourcemap for karma-sourcemap-loader
  // 使用sourceMap便于调试
  module: {
    rules: utils.styleLoaders()
  },
  devtool: '#inline-source-map',
  resolveLoader: {
    alias: {
      // necessary to to make lang="scss" work in test when using vue-loader's ?inject option
      // see discussion at https://github.com/vuejs/vue-loader/issues/724
      // 解决了一个设置lang="scss"的bug问题
      'scss-loader': 'sass-loader'
    }
  },
  plugins: [
    // 定义全局变量,webpack打包时会对变量做替换
    new webpack.DefinePlugin({
      'process.env': require('../config/test.env')
    })
  ]
})

// no need for app entry during tests
// 测试时将入口文件删除(用意?)
delete webpackConfig.entry

module.exports = webpackConfig

check-versions.js和dev-client.js

说明:

check-versions.js主要是对node和npm的版本检测 dev-client.js用来控制浏览器重新加载

详情:

check-versions.js

// 彩色命令行插件
var chalk = require('chalk')
// 语义化版本检查插件
var semver = require('semver')
// package.json文件
var packageConfig = require('../package.json')
// Unix命令行工具
var shell = require('shelljs')
// 开辟子进程执行cmd并返回结果
function exec (cmd) {
  return require('child_process').execSync(cmd).toString().trim()
}

// node和npm版本需求
var versionRequirements = [
  {
    name: 'node',
    // process.version 返回一个字符串,表示当前使用的node版本
    currentVersion: semver.clean(process.version),
    // 取出package.json中设定的node版本
    versionRequirement: packageConfig.engines.node
  }
]

// 判断系统的环境变量中是否有npm
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)
  }
}

dev-client.js

/* eslint-disable */
require('eventsource-polyfill')
// 调用插件的一个模块,传入参数(?)
var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')

// 事件重写
hotClient.subscribe(function (event) {
  if (event.action === 'reload') {
    window.location.reload()
  }
})

config文件分析

config文件是项目项目相关配置信息,包含打包、开发设置

index.js

说明:

详细:

// 项目结构说明 http://vuejs-templates.github.io/webpack
var path = require('path')

module.exports = {
  // 构建时使用的配置
  build: {
    // 环境变量
    env: require('./prod.env'),
    // 获得index.html的绝对路径
    index: path.resolve(__dirname, '../dist/index.html'),
    // webpack编译输出的目标文件夹路径
    assetsRoot: path.resolve(__dirname, '../dist'),
    // webpack编译输出的(二级文件夹)静态资源文件夹
    assetsSubDirectory: 'static',
    // webpack编译输出的发布路径
    assetsPublicPath: '/',
    // 是否使用sourceMap
    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模式下,需要压缩的格式
    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
    // 是否开启分析js文件的功能
    bundleAnalyzerReport: process.env.npm_config_report
  },
  // 开发时使用的配置
  dev: {
    // 编译环境变量
    env: require('./dev.env'),
    // dev-server监听的端口
    port: 8080,
    // 是否自动打开浏览器
    autoOpenBrowser: true,
    // webpack编译输出的二级文件夹
    assetsSubDirectory: 'static',
    // webpack编译输出的发布路径
    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
    cssSourceMap: false
  }
}

dev.env.js/prod.env.js/test.env.js

说明:

用来设置环境变量,开发时、构建时、测试时。

详细:

dev.env.js

// 用于合并对象、数组
var merge = require('webpack-merge')
// 生产环境的环境变量
var prodEnv = require('./prod.env')

// 用"development"覆盖"production"
module.exports = merge(prodEnv, {
  NODE_ENV: '"development"'
})

prod.env.js

// 定义环境变量
module.exports = {
  NODE_ENV: '"production"'
}

test.env.js

// 用于合并对象、数组
var merge = require('webpack-merge')
// 取得开发时设置的环境变量
var devEnv = require('./dev.env')

// 使用"testing"覆盖"development"
module.exports = merge(devEnv, {
  NODE_ENV: '"testing"'
})

参考文档

  1. assets和static目录的区别
  2. 项目结构
  3. 别名和-D -S
  4. what's process
  5. opn
  6. node-open
  7. node/path
  8. webpack-dev-middleware[publicPath]
  9. Promise对象
  10. Data URL
  11. webpack.DefinePlugin
  12. Vue.js的实用技巧
  13. module.id保持稳定
  14. webpack构建之hash缓存的利用
  15. JavsScript Source Map 详解
  16. vue-cli的webpack模板项目配置文件解析
  17. vue-cli#2.0 webpack 配置分析
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment