vue-cli 目次构造细致解说

[toc]

目次

构造预览

├─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

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效劳器。

// 搜检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内里另行设置。

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插件
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拓荒环境的wepack相干设置文件,重要用来处置惩罚css-loader和vue-style-loader

// 引入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
}

extract-text-webpack-plugin插件是用来将文本从bundle中提取到一个零丁的文件中

const ExtractTextPlugin = require("extract-text-webpack-plugin");
 module.exports = {
   module: {
     rules: [
       {
         test: /\.css$/, //重要用来处置惩罚css文件
         use: ExtractTextPlugin.extract({
           fallback: "style-loader", // fallback示意假如css文件没有胜利导入就运用style-loader导入
           use: "css-loader" // 示意运用css-loader从js读取css文件
         })
       }
     ],
     plugins: [
       new ExtractTextPlugin("styles.css") //示意天生styles.css文件
     ]
   }
 }

vue-loader.conf.js

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的热更新。

/* 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编译以后会输出到设置内里指定的目的文件夹;删除目的文件夹以后再竖立是为了去除旧的内容,以防止发生不可展望的影响。

// 搜检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'
    ))
  })
})

webpack.prod.conf.js

构建的时刻用到的webpack设置来自webpack.prod.conf.js,该设置同样是在webpack.base.conf基础上的进一步完美。重要完成下面几件事变:

  • 兼并基础的webpack设置
  • 设置款式文件的处置惩罚划定规矩,styleLoaders
  • 设置webpack的输出
  • 设置webpack插件
  • gzip形式下的webpack插件设置
  • webpack-bundle剖析

申明: webpack插件内里多了丑化紧缩代码以及抽离css文件等插件。

var path = require('path')
var utils = require('./utils')
var webpack = require('webpack')
var config = require('../config')
var merge = require('webpack-merge')
var baseWebpackConfig = require('./webpack.base.conf')
// copy-webpack-plugin,用于将static中的静态文件复制到产物文件夹dist
var CopyWebpackPlugin = require('copy-webpack-plugin')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
// optimize-css-assets-webpack-plugin,用于优化和最小化css资本
var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')

var env = config.build.env

var webpackConfig = merge(baseWebpackConfig, {
  module: {
    // 款式文件的处置惩罚划定规矩,对css/sass/scss等差别内容运用响应的styleLoaders
    // 由utils设置出种种范例的预处置惩罚言语所须要运用的loader,比方sass须要运用sass-loader
    rules: utils.styleLoaders({
      sourceMap: config.build.productionSourceMap,
      extract: true
    })
  },
  // 是不是运用source-map
  devtool: config.build.productionSourceMap ? '#source-map' : false,
  // webpack输出途径和定名划定规矩
  output: {
    path: config.build.assetsRoot,
    filename: utils.assetsPath('js/[name].[chunkhash].js'),
    chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
  },
  // webpack插件
  plugins: [
    // http://vuejs.github.io/vue-loader/en/workflow/production.html
    new webpack.DefinePlugin({
      'process.env': env
    }),
    // 丑化紧缩JS代码
    new webpack.optimize.UglifyJsPlugin({
      compress: {
        warnings: false
      },
      sourceMap: true
    }),
    // extract css into its own file
    // 将css提取到零丁的文件
    new ExtractTextPlugin({
      filename: utils.assetsPath('css/[name].[contenthash].css')
    }),
    // Compress extracted CSS. We are using this plugin so that possible
    // duplicated CSS from different components can be deduped.
    // 优化、最小化css代码,假如只简朴运用extract-text-plugin可能会形成css反复
    // 详细缘由能够看npm上面optimize-css-assets-webpack-plugin的引见
    new OptimizeCSSPlugin({
      cssProcessorOptions: {
        safe: true
      }
    }),
    // generate dist index.html with correct asset hash for caching.
    // you can customize output by editing /index.html
    // see https://github.com/ampedandwired/html-webpack-plugin
    // 将产物文件的援用注入到index.html
    new HtmlWebpackPlugin({
      filename: config.build.index,
      template: 'index.html',
      inject: true,
      minify: {
        // 删除index.html中的解释
        removeComments: true,
        // 删除index.html中的空格
        collapseWhitespace: true,
        // 删除种种html标签属性值的双引号
        removeAttributeQuotes: true
        // more options:
        // https://github.com/kangax/html-minifier#options-quick-reference
      },
      // necessary to consistently work with multiple chunks via CommonsChunkPlugin
      // 注入依靠的时刻根据依靠先后顺序举行注入,比方,须要先注入vendor.js,再注入app.js
      chunksSortMode: 'dependency'
    }),
    // keep module.id stable when vender modules does not change
    new webpack.HashedModuleIdsPlugin(),
    // split vendor js into its own file
    // 将一切从node_modules中引入的js提取到vendor.js,即抽取库文件
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: function (module, count) {
        // any required modules inside node_modules are extracted to vendor
        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
    // 从vendor中提掏出manifest,缘由如上
    new webpack.optimize.CommonsChunkPlugin({
      name: 'manifest',
      chunks: ['vendor']
    }),
    // copy custom static assets
    // 将static文件夹内里的静态资本复制到dist/static
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, '../static'),
        to: config.build.assetsSubDirectory,
        ignore: ['.*']
      }
    ])
  ]
})

// 假如开启了产物gzip紧缩,则应用插件将构建后的产物文件举行紧缩
if (config.build.productionGzip) {
  // 一个用于紧缩的webpack插件
  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
    })
  )
}

// 假如启动了report,则经由历程插件给出webpack构建打包后的产物文件剖析报告
if (config.build.bundleAnalyzerReport) {
  var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}

module.exports = webpackConfig

check-versions.js

// 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内里的设置

// 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
  }
}
'use strict'
const path = require('path')

module.exports = {
  dev: {
    // 拓荒环境下面的设置
    assetsSubDirectory: 'static',//子目次,寻常寄存css,js,image等文件
    assetsPublicPath: '/',//根目次
    proxyTable: {},//可应用该属性处理跨域的题目
    host: 'localhost', // 地点
    port: 8080, //端口号设置,端口号占用出现题目可在此处修正
    autoOpenBrowser: false,//是不是在编译(输入敕令行npm run dev)后翻开http://localhost:8080/页面,之前设置为true,近些版本改成false,个人倾向习气自动翻开页面
    errorOverlay: true,//浏览器毛病提醒
    notifyOnErrors: true,//跨平台毛病提醒
    poll: false, //运用文件体系(file system)猎取文件修改的关照devServer.watchOptions
    devtool: 'cheap-module-eval-source-map',//增添调试,该属性为原始源代码(仅限行)不可在临盆环境中运用
    cacheBusting: true,//使缓存失效
    cssSourceMap: true//代码紧缩后举行调bug定位将异常难题,因而引入sourcemap纪录紧缩前后的位置信息纪录,当发生毛病时直接定位到未紧缩前的位置,将大大的轻易我们调试
  },

  build: {
  // 临盆环境下面的设置
    index: path.resolve(__dirname, '../dist/index.html'),//index编译后天生的位置和名字,依据须要转变后缀,比方index.php
    assetsRoot: path.resolve(__dirname, '../dist'),//编译后寄存天生环境代码的位置
    assetsSubDirectory: 'static',//js,css,images寄存文件夹名
    assetsPublicPath: '/',//宣布的根目次,一般当地打包dist后翻开文件会报错,此处修正为./。假如是上线的文件,可依据文件寄存位置举行变动途径
    productionSourceMap: true,
    devtool: '#source-map',//①
    //unit的gzip敕令用来紧缩文件,gzip形式下须要紧缩的文件的扩展名有js和css
    productionGzip: false,
    productionGzipExtensions: ['js', 'css'],
    bundleAnalyzerReport: process.env.npm_config_report
  }
}

prod.env.js

当拓荒是调取dev.env.js的拓荒环境设置,宣布时挪用prod.env.js的临盆环境设置

'use strict'
module.exports = {
  NODE_ENV: '"production"'
}

dev.env.js

config内的文件实际上是效劳于build的,大部分是定义一个变量export出去。

'use strict'//采纳严厉形式
const merge = require('webpack-merge')//①
const prodEnv = require('./prod.env')
//webpack-merge供应了一个兼并函数,它将数组和兼并对象竖立一个新对象。
//假如碰到函数,它将实行它们,经由历程算法运转效果,然后再次将返回的值封装在函数中.这边将dev和prod举行兼并
module.exports = merge(prodEnv, {
  NODE_ENV: '"development"'
})

src

①、assets文件:脚手架自动会放入一个图片在内里作为初始页面的logo。寻常我们运用的时刻会在内里竖立js,css,img,fonts等文件夹,作为静态资本挪用

②、components文件夹:用来寄存组件,合理地运用组件能够高效地完成复用等功用,从而更好地拓荒项目。寻常情况下比方竖立头部组件的时刻,我们会新建一个header的文件夹,然后再新建一个header.vue的文件

③、router文件夹:该文件夹下有一个叫index.js文件,用于完成页面的路由跳转,详细运用请点击→vue-router传送门

④、App.vue:作为我们的主组件,可经由历程运用<router-view/>开放进口让其他的页面组件得以显现。

⑤、main.js:作为我们的进口文件,重要作用是初始化vue实例并运用须要的插件,小型项目省略router时可放在该处

.babelrc

{
//制订转码的划定规矩
  "presets": [
  //env是运用babel-preset-env插件将js举行转码成es5,而且设置不转码的AMD,COMMONJS的模块文件,制订浏览器的兼容
    ["env", {
      "modules": false,
      "targets": {
        "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
      }
    }],
    "stage-2"
  ],
  
  "plugins": ["transform-vue-jsx", "transform-runtime"]//①
}

.postcessrc.js

.postcssrc.js文件实际上是postcss-loader包的一个设置,在webpack的旧版本能够直接在webpack.config.js中设置,现版本中postcss的文档示例自力出.postcssrc.js,内里写进去须要运用到的插件

module.exports = {
  "plugins": {
    "postcss-import": {},//①
    "postcss-url": {},//②
    "autoprefixer": {}//③
  }
}

package.json

package.json来制订名单,须要哪些npm包来介入到项目中来,npm install敕令依据这个设置文件增减来治理当地的装置包

{
//从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"
  ]
}

解释:

①、点这里→webpack运转时的设置文档传送门

②、devDependencies和dependencies的区分: devDependencies内里的插件只用于拓荒环境,不用于临盆环境,即辅佐作用,打包的时刻须要,打包完成就不须要了。而dependencies是须要宣布到临盆环境的,自始至终都在。比方wepack等只是在拓荒中运用的包就写入到devDependencies,而像vue这类项目全程依靠的包要写入到dependencies

点这里→更多装置包文档搜刮页传送门

③、file-loader和url-loader的区分:以图片为例,file-loader可对图片举行紧缩,然则照样经由历程文件途径举行引入,当http要求增加时会下降页面机能,而url-loader经由历程设定limit参数,小于limit字节的图片会被转成base64的文件,大于limit字节的将举行图片紧缩的操纵。总而言之,url-loader是file-loader的上层封装。

点这里→file-loader 和 url-loader详解

点这里→file-loader文档传送门

点这里→url-loader文档传送门

其他文件

①、.editorconfig:编辑器的设置文件

②、.gitignore:疏忽git提交的一个文件,设置以后提交时将不会加载疏忽的文件

③、index.html:页面进口,经由编译以后的代码将插进去到这来。

④、package.lock.json:锁定装置时的包的版本号,而且须要上传到git,以保证其他人在npm install时人人的依靠能保证一致

⑤、README.md:可此填写项目引见

⑥、node_modules:依据package.json装置时刻天生的的依靠(装置包)

其他好的博客笔记

vue-cli的webpack模板项目设置文件剖析

vue-cli脚手架中webpack设置基础文件详解

    原文作者:jieyuanfei
    原文地址: https://segmentfault.com/a/1190000017828766
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞