Vue CLI 2.x搭建Vue项目

使用vue-cli2.x脚手架搭建一个vue项目,以及目录结构分析。

一、Node安装

 windows
 1. Node.js (>=6.x, 推荐8.x)
  Node官网下载 .msi 文件,按步骤下载安装即可。
  安装完之后在cmd中输入 node -v,若显示版本号,则说明安装成功。
 2. Git(命令行终端)
  Git官网下载安装即可。

 linux

apt-get install nodejs
node -v
apt-get install npm
npm -v

 npm命令
 1. 得到原本的镜像地址

npm get registry

 2. 设成淘宝的

npm config set registry http://registry.npm.taobao.org/

 3. 换成原来的

npm config set registry https://registry.npmjs.org/

二、vue-cli安装、更新

  vue-cli是一个用于快速搭建vue项目的脚手架。
  安装过Node.js、Git后,全局安装vue-cli(以后其他项目可直接使用):

npm install -g vue-cli

  更新:

npm update vue-cli

  查看安装成功否(有版本号就是成功,V大写)

vue -V

三、vue-cli搭建vue项目

  执行如下命令即可。

vue init webpack my-project

vue_cli2x_init.png
  PS:ESLint(一个javascript代码检测工具)、unit tests(单元测试)、Nightwatch(一个e2e用户界面测试工具)。这里暂时都选N,其它的直接回车即可。
  然后依次执行 cd my-projectnpm run dev 即可访问vue默认的demo页面。
vue_cli2x_helloworld_page.png

  下面是一些特殊情况的处理:

  如果当前安装的Vue CLI >= 3,那么需要拉取2.x 模板(旧版本)。
  Vue CLI >= 3 和旧版使用了相同的 vue 命令,所以 Vue CLI 2 (vue-cli) 被覆盖了。如果你仍然需要使用旧版本的 vue init 功能,你可以全局安装一个桥接工具:

npm install -g @vue/cli-init
# `vue init` 的运行效果将会跟 `vue-cli@2.x` 相同
vue init webpack my-project

  vue init < template-name > < project-name >
  用于初始化一个vue项目,该命令有两个参数,第一个是模板名,第二个是项目名。
  目前可用的模块包括:
  webpack - 一个功能齐全的Webpack + vue-loader设置,具有热重载,linting,测试和css提取功能。
  webpack-simple - 一个简单的Webpack + vue-loader设置,用于快速原型设计。
  browserify -全功能Browserify + vueify设置用热重装载,linting&单元测试。
  browserify -simple - 一个简单的Browserify + vueify设置,用于快速原型设计。
  pwa - 基于webpack模板的vue-cli的PWA模板
  simple - 单个HTML文件中最简单的Vue设置

四、相关文件和文件夹的含义

  使用 vue-cli2.x 脚手架工具创建vue项目后,整个项目目录结构如下图所示:
vue_cli2x_dir_list.png

1. build文件夹

  build文件夹的结构:
vue_cli2x_dir_build.png
  ① build.js

'use strict'
require('./check-versions')()  // 调用版本检查

process.env.NODE_ENV = 'production'  // 将环境配置为生产环境

const ora = require('ora')  // npm包 loading插件
const rm = require('rimraf')  // npm包 用于删除文件
const path = require('path')  // npm包 文件路径工具
const chalk = require('chalk')  // npm包 在终端输出带颜色的文字
const webpack = require('webpack')  // 引入webpack.js
const config = require('../config')  // 引入配置文件
const webpackConfig = require('./webpack.prod.conf')  // 引入生产环境配置文件

// 在终端显示loading效果,并输出提示
const spinner = ora('building for production...')
spinner.start()

// 先递归删除dist文件再生成新文件,避免冗余
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
  if (err) throw err
  webpack(webpackConfig, (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'
    ))
  })
})

  ps:require/export是一种nodeJs(commonJs规范)的依赖注入的方法,import/export是ES6语法,用于引入模块,在nodeJs中使用的ES6语法最终会使用babel工具(babel-loader)转化为ES5。

  ② check-version.js
  检测node和npm的版本,实现版本依赖。

'use strict'
const chalk = require('chalk')
const semver = require('semver')  // 检查版本
const packageConfig = require('../package.json')
const shell = require('shelljs')  // shelljs 模块重新包装了 child_process,调用系统命令更加方便

function exec (cmd) {  // 返回通过child_process模块的新建子进程,执行 Unix 系统命令后转成没有空格的字符串
  return require('child_process').execSync(cmd).toString().trim()
}

const versionRequirements = [
  {
    name: 'node',
    currentVersion: semver.clean(process.version),  // 使用semver格式化版本
    versionRequirement: packageConfig.engines.node  // 获取package.json中设置的node版本
  }
]

if (shell.which('npm')) {
  versionRequirements.push({
    name: 'npm',
    currentVersion: exec('npm --version'),  // 自动调用npm --version命令,并且把参数返回给exec函数,从而获取纯净的版本号
    versionRequirement: packageConfig.engines.npm
  })
}

module.exports = function () {
  const warnings = []

  for (let i = 0; i < versionRequirements.length; i++) {
    const mod = versionRequirements[i]

    // 若版本号不符合package.json文件中指定的版本号,就报错
    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 (let i = 0; i < warnings.length; i++) {
      const warning = warnings[i]
      console.log('  ' + warning)
    }

    console.log()
    process.exit(1)
  }
}

  ③ utils.js
  utils是工具的意思,是一个用来处理css的文件,这个文件包含了三个工具函数:
  • 生成静态资源的路径
  • 生成 ExtractTextPlugin对象或loader字符串
  • 生成 style-loader的配置

'use strict'
const path = require('path')  // node自带的文件路径工具
const config = require('../config')  // 配置文件
const ExtractTextPlugin = require('extract-text-webpack-plugin')  // 提取css的插件
const packageConfig = require('../package.json')


/** @method assertsPath  生成静态资源的路径(判断开发环境和生产环境,为config文件中index.js文件中定义assetsSubDirectory)
 * @param  {String}      _path 相对于静态资源文件夹的文件路径
 * @return {String}      静态资源完整路径
 */
exports.assetsPath = function (_path) {
  const assetsSubDirectory = process.env.NODE_ENV === 'production'
    ? config.build.assetsSubDirectory
    : config.dev.assetsSubDirectory

  // nodeJs path提供用于处理文件路径的工具;path.posix提供对路径方法的POSIX(可移植性操作系统接口)特定实现的访问(可跨平台); path.posix.join与path.join一样,不过总是以 posix 兼容的方式交互
  return path.posix.join(assetsSubDirectory, _path)
}

/**@method cssLoaders  生成处理css的loaders配置,使用css-loader和postcssLoader,通过options.usePostCSS属性来判断是否使用postcssLoader中压缩等方法
 * @param  {Object} option = {sourceMap: true,// 是否开启 sourceMapextract: true // 是否提取css}生成配置
 * @return {Object} 处理css的loaders配置对象
 */
exports.cssLoaders = function (options) {
  options = options || {}

  const cssLoader = {
    loader: 'css-loader',
    options: {
      sourceMap: options.sourceMap
    }
  }

  const postcssLoader = {
    loader: 'postcss-loader',
    options: {
      sourceMap: options.sourceMap
    }
  }

  /**@method generateLoaders  生成 ExtractTextPlugin对象或loader字符串
   * @param  {Array}        loaders loader名称数组
   * @return {String|Object}        ExtractTextPlugin对象或loader字符串
   */
  function generateLoaders (loader, loaderOptions) {
    const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]

    if (loader) {
      loaders.push({
        loader: loader + '-loader',
        options: Object.assign({}, loaderOptions, {
          sourceMap: options.sourceMap
        })
      })
    }

    // ExtractTextPlugin提取css(当上面的loaders未能正确引入时,使用vue-style-loader)
    if (options.extract) {
      return ExtractTextPlugin.extract({
        use: loaders,
        fallback: 'vue-style-loader'
      })
    } else {
      return ['vue-style-loader'].concat(loaders)
    }
  }

  return {
    css: generateLoaders(),  // 需要css-loader 和 vue-style-loader
    postcss: generateLoaders(),  // 需要css-loader、postcssLoader 和 vue-style-loader
    less: generateLoaders('less'),  // 需要less-loader 和 vue-style-loader
    sass: generateLoaders('sass', { indentedSyntax: true }),  // 需要sass-loader 和 vue-style-loader
    scss: generateLoaders('sass'),  // 需要sass-loader 和 vue-style-loader
    stylus: generateLoaders('stylus'),  // 需要stylus-loader 和 vue-style-loade
    styl: generateLoaders('stylus')  // 需要stylus-loader 和 vue-style-loader
  }
}

/**@method styleLoaders 生成 style-loader的配置
 * @param  {Object}     options 生成配置
 * @return {Array}      style-loader的配置
 */
exports.styleLoaders = function (options) {
  const output = []
  const loaders = exports.cssLoaders(options)

  // 将各种css,less,sass等综合在一起得出结果输出output
  for (const extension in loaders) {
    const loader = loaders[extension]
    output.push({
      test: new RegExp('\\.' + extension + '$'),
      use: loader
    })
  }

  return output
}

exports.createNotifierCallback = () => {
  const notifier = require('node-notifier')

  return (severity, errors) => {
    if (severity !== 'error') return

    const error = errors[0]
    const filename = error.file && error.file.split('!').pop()

    notifier.notify({
      title: packageConfig.name,
      message: severity + ': ' + error.name,
      subtitle: filename || '',
      icon: path.join(__dirname, 'logo.png')
    })
  }
}

  ④ vue-loader.conf.js
  处理.vue文件,解析这个文件中的每个语言块(template、script、style),转换成js可用的js模块。

'use strict'
const utils = require('./utils')
const config = require('../config')
const isProduction = process.env.NODE_ENV === 'production'
// 生产环境,提取css样式到单独文件
const sourceMapEnabled = isProduction
  ? config.build.productionSourceMap
  : config.dev.cssSourceMap

module.exports = {
  loaders: utils.cssLoaders({
    sourceMap: sourceMapEnabled,
    extract: isProduction
  }),
  cssSourceMap: sourceMapEnabled,
  cacheBusting: config.dev.cacheBusting,
  // 编译时将“引入路径”转换为require调用,使其可由webpack处理
  transformToRequire: {
    video: ['src', 'poster'],
    source: 'src',
    img: 'src',
    image: 'xlink:href'
  }
}

  ⑤ webpack.base.conf.js
  开发、测试、生产环境的公共基础配置文件,配置输出环境,配置模块resolve和插件等。

'use strict'
const path = require('path')  // node自带的文件路径工具
const utils = require('./utils')  // 工具函数集合
const config = require('../config')  // 配置文件
const vueLoaderConfig = require('./vue-loader.conf')  // 工具函数集合

/**
 * 获取"绝对路径"
 * @method resolve
 * @param  {String} dir 相对于本文件的路径
 * @return {String}     绝对路径
 */
function resolve (dir) {
  return path.join(__dirname, '..', dir)
}

module.exports = {
  context: path.resolve(__dirname, '../'),
  // 入口js文件(默认为单页面所以只有app一个入口)
  entry: {
    app: './src/main.js'
  },
  // 配置出口
  output: {
    path: config.build.assetsRoot,  // 打包编译的根路径(dist)
    filename: '[name].js',
    publicPath: process.env.NODE_ENV === 'production'
      ? config.build.assetsPublicPath
      : config.dev.assetsPublicPath  // 发布路径
  },
  resolve: {
    extensions: ['.js', '.vue', '.json'],  // 自动补全的扩展名
    // 别名配置
    alias: {
      'vue$': 'vue/dist/vue.esm.js',
      '@': resolve('src'),  // eg:"src/components" => "@/components"
    }
  },
  module: {
    rules: [
      // 使用vue-loader将vue文件编译转换为js
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: vueLoaderConfig
      },
      // 通过babel-loader将ES6编译压缩成ES5
      {
        test: /\.js$/,
        loader: 'babel-loader',
        include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
      },
      // 使用url-loader处理(图片、音像、字体),超过10000编译成base64
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
        loader: 'url-loader',
        options: {
          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]')
        }
      }
    ]
  },
  // nodeJs全局变量/模块,防止webpack注入一些nodeJs的东西到vue中
  node: {
    setImmediate: false,
    dgram: 'empty',
    fs: 'empty',
    net: 'empty',
    tls: 'empty',
    child_process: 'empty'
  }
}

  ⑥ webpack.dev.conf.js
  webpack配置开发环境中的入口,这里面的配置一般不建议去动,否则遇到什么问题需要上网去查相关配置怎么写。

'use strict'
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')  // webpack-merge实现合并
const path = require('path')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')  // webpack的提示错误和日志信息的插件
const portfinder = require('portfinder')  // 查看空闲端口位置,默认情况下搜索8000这个端口

const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)

const devWebpackConfig = merge(baseWebpackConfig, {
  module: {
    rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
  },
  devtool: config.dev.devtool,  // 调试模式

  devServer: {
    clientLogLevel: 'warning',
    historyApiFallback: {  // 使用 HTML5 History API 时, 404 响应替代为 index.html
      rewrites: [
        { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
      ],
    },
    hot: true,  // 热重载
    contentBase: false, // 提供静态文件访问
    compress: true,  // 压缩
    host: HOST || config.dev.host,
    port: PORT || config.dev.port,
    open: config.dev.autoOpenBrowser,  // npm run dev 时自动打开浏览器
    overlay: config.dev.errorOverlay
      ? { warnings: false, errors: true }
      : false,  // 显示warning 和 error 信息
    publicPath: config.dev.assetsPublicPath,
    proxy: config.dev.proxyTable,  // api代理
    quiet: true, // 控制台打印警告和错误(用FriendlyErrorsPlugin 为 true)
    watchOptions: {  // 检测文件改动
      poll: config.dev.poll,
    }
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': require('../config/dev.env')
    }),
    new webpack.HotModuleReplacementPlugin(),  // 模块热替换插件,修改模块时不需要刷新页面
    new webpack.NamedModulesPlugin(),  // HMR shows correct file names in console on update.
    new webpack.NoEmitOnErrorsPlugin(),  // webpack编译错误的时候,中断打包进程,防止错误代码打包到文件中
    // 将打包编译好的代码插入index.html
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'index.html',
      inject: true
    }),
    // 提取static assets 中css 复制到dist/static文件
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, '../static'),
        to: config.dev.assetsSubDirectory,
        ignore: ['.*']  // 忽略.*的文件
      }
    ])
  ]
})

module.exports = new Promise((resolve, reject) => {
  portfinder.basePort = process.env.PORT || config.dev.port
  portfinder.getPort((err, port) => {  // 查找端口号
    if (err) {
      reject(err)
    } else {
      // 端口被占用时就重新设置evn和devServer的端口
      process.env.PORT = port
      devWebpackConfig.devServer.port = port
      // npm run dev成功的友情提示
      devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
        compilationSuccessInfo: {
          messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
        },
        onErrors: config.dev.notifyOnErrors
        ? utils.createNotifierCallback()
        : undefined
      }))

      resolve(devWebpackConfig)
    }
  })
})

  ⑦ webpack.dev.prod.js
  webpack配置生产环境中的入口。

'use strict'
const path = require('path')
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')

const env = require('../config/prod.env')

const webpackConfig = merge(baseWebpackConfig, {
  module: {
    rules: utils.styleLoaders({
      sourceMap: config.build.productionSourceMap,
      extract: true,
      usePostCSS: true
    })
  },
  devtool: config.build.productionSourceMap ? config.build.devtool : false,  // 是否开启调试模式
  output: {
    path: config.build.assetsRoot,
    filename: utils.assetsPath('js/[name].[chunkhash].js'),
    chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
  },
  plugins: [
    new webpack.DefinePlugin({
      'process.env': env
    }),
    new UglifyJsPlugin({  // 压缩js
      uglifyOptions: {
        compress: {
          warnings: false
        }
      },
      sourceMap: config.build.productionSourceMap,
      parallel: true
    }),
    new ExtractTextPlugin({  // 提取静态文件,减少请求
      filename: utils.assetsPath('css/[name].[contenthash].css'),
      allChunks: true,
    }),
    new OptimizeCSSPlugin({  // 提取优化压缩后(删除来自不同组件的冗余代码)的css
      cssProcessorOptions: config.build.productionSourceMap
        ? { safe: true, map: { inline: false } }
        : { safe: true }
    }),
    new HtmlWebpackPlugin({  // html打包压缩到index.html
      filename: config.build.index,
      template: 'index.html',
      inject: true,
      minify: {
        removeComments: true,  // 删除注释
        collapseWhitespace: true,  // 删除空格
        removeAttributeQuotes: true  // 删除属性的引号
      },
      chunksSortMode: 'dependency'  // 模块排序,按照我们需要的顺序排序
    }),
    new webpack.HashedModuleIdsPlugin(),
    new webpack.optimize.ModuleConcatenationPlugin(),
    new webpack.optimize.CommonsChunkPlugin({  // node_modules中的任何所需模块都提取到vendor
      name: 'vendor',
      minChunks (module) {
        return (
          module.resource &&
          /\.js$/.test(module.resource) &&
          module.resource.indexOf(
            path.join(__dirname, '../node_modules')
          ) === 0
        )
      }
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'manifest',
      minChunks: Infinity
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'app',
      async: 'vendor-async',
      children: true,
      minChunks: 3
    }),

    new CopyWebpackPlugin([  // 复制static中的静态资源(默认到dist里面)
      {
        from: path.resolve(__dirname, '../static'),
        to: config.build.assetsSubDirectory,
        ignore: ['.*']
      }
    ])
  ]
})

if (config.build.productionGzip) {
  const 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
    })
  )
}

if (config.build.bundleAnalyzerReport) {
  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}

module.exports = webpackConfig

2. config文件夹

  config文件夹的结构:
vue_cli2x_dir_config.png
  ① dev.env.js和prod.env.js
  分别配置:开发环境和生产环境。这个可以根据公司业务结合后端需求配置需要区分开发环境和测试环境的属性。
  dev.env.js

'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')

module.exports = merge(prodEnv, {
  NODE_ENV: '"development"'
})

  ps:webpack-merge用于实现合并类似于ES6的Object.assign()

  prod.env.js

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

  (*注意属性值要用'""'双层引住),访问(获取值)时直接用:process.env.属性名
  ps:process(进程)是nodejs的一个全局变量,process.env 属性返回一个用户环境信息的对象。

  ② index.js

'use strict'

const path = require('path')

module.exports = {
  // ===================开发环境配置
  dev: {
    assetsSubDirectory: 'static',  // 静态资源文件夹(一般存放css、js、image等文件)
    assetsPublicPath: '/',  // 根目录
    proxyTable: {},  // 配置API代理,可利用该属性解决跨域的问题
    host: 'localhost', // 可以被 process.env.HOST 覆盖
    port: 8080,  // 可以被 process.env.PORT 覆盖
    autoOpenBrowser: false,  // 编译后自动打开浏览器页面 http://localhost:8080/("port + host",默认"false"),设置路由重定向自动打开您的默认页面
    errorOverlay: true,  // 浏览器错误提示
    notifyOnErrors: true,  // 跨平台错误提示
    poll: false,  // webpack提供的使用文件系统(file system)获取文件改动的通知devServer.watchOptions(监控文件改动)
    devtool: 'cheap-module-eval-source-map',  // webpack提供的用来调试的模式,有多个不同值代表不同的调试模式
    cacheBusting: true,  // 配合devtool的配置,当给文件名插入新的hash导致清除缓存时是否生成source-map
    cssSourceMap: true  // 记录代码压缩前的位置信息,当产生错误时直接定位到未压缩前的位置,方便调试
  },

  // ========================生产环境配置
  build: {
    index: path.resolve(__dirname, '../dist/index.html'),  // 编译后"首页面"生成的绝对路径和名字
    assetsRoot: path.resolve(__dirname, '../dist'),  // 打包编译的根路径(默认dist,存放打包压缩后的代码)
    assetsSubDirectory: 'static',  // 静态资源文件夹(一般存放css、js、image等文件)
    assetsPublicPath: '/',  // 发布的根目录(dist文件夹所在路径)
    productionSourceMap: true,  // 是否开启source-map
    devtool: '#source-map',  // (详细参见:https://webpack.docschina.org/configuration/devtool)
    productionGzip: false,  // 是否压缩
    productionGzipExtensions: ['js', 'css'],  // unit的gzip命令用来压缩文件(gzip模式下需要压缩的文件的扩展名有js和css)
    bundleAnalyzerReport: process.env.npm_config_report  // 是否开启打包后的分析报告
  }
}

3. node_modules文件夹

  存放npm install时根据package.json配置生成的npm安装包的文件夹

4. src文件夹

  src目录中的文件如下图所示。
vue_cli2x_dir_src.png
  我们需要在src文件夹中开发代码,打包时webpack会根据build中的规则(build规则依赖于config中的配置)将src打包压缩到dist文件夹在浏览器中运行。
  ① assets文件夹
  用于存放静态资源(css、image),assets打包时路径会经过webpack中的file-loader编译(因此,assets需要使用绝对路径)成js。
  ② components文件夹
  用来存放 .vue 组件(实现复用等功能,如:过滤器,列表项等)。
  ③ router文件夹
  在router/index.js文件中配置页面路由。

import Vue from 'vue'
import Router from 'vue-router'
import HelloWorld from '@/components/HelloWorld'  // 这里@符号是在build/webpack.base.conf.js中的resolve配置的别名,相当于获取当前项目目录

Vue.use(Router)  // 此时的router对象是一个局部作用域,需要挂载到Vue原型,才能在任意组件中调用 this.$router 和 this.$route

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld
    }
  ]
})

  ④ App.vue
  是整个项目的主组件,所有页面都是通过使用开放入口在App.vue下进行切换的(所有的路由都是App.vue的子组件)。
  ⑤ main.js
  入口js文件(全局js,你可以在这里:初始化vue实例、require/import需要的插件、注入router路由、引入store状态管理)。

5. static文件夹

  webpack默认存放静态资源(css、image)的文件夹,与assets不同的是:static在打包时会直接复制一个同名文件夹到dist文件夹里(不会经过编译,可使用相对路径)。
  一般情况下,assets放当前项目的静态资源(每个组件内部的静态资源),static放公共静态资源

6. 其他文件

  ① .babelrc
  浏览器解析的兼容配置,该文件主要是对预设(presets)和插件(plugins)进行配置,因此不同的转译器作用不同的配置项,大致可分为:语法转义器、补丁转义器、sx和flow插件。
  ② .editorconfig
  用于配置代码格式(配合代码检查工具使用,如:ESLint,团队开发时可统一代码风格),这里配置的代码规范规则优先级高于编辑器默认的代码格式化规则。
  ③ .gitignore
  配置git提交时需要忽略的文件。
  ④ postcssrc.js
  autoprefixer(自动补全css样式的浏览器前缀);postcss-import(@import引入语法)、CSS Modules(规定样式作用域)。
  ⑤ index.html
  项目入口页面,编译之后所有代码将插入到这来。
  ⑥ package.json
  npm的配置文件(npm install根据package.json下载对应版本的安装包)。
  ⑦ package.lock.json
  npm install(安装)时锁定各包的版本号。
  ⑧ README.md
  项目使用说明。

五、vue-cli 3x

  了解 vue-cli 3x 参见本人另一篇博客《Vue CLI 3.x搭建Vue项目》


参考
https://github.com/vuejs/vue-cli/tree/v2
https://cli.vuejs.org/zh/guide/creating-a-project.html#拉取-2-x-模板-旧版本


  目录