vue-cli腳手架-bulid下的配置文件

本文章適合初學者學習,若有錯請提出。近期對vue比較感興趣,因此準備用vue寫一個blog。早期先對vue腳手架了解一下,對於新手官網建議先不用vue-cli,但我以爲若是沒有任何的依據憑本身寫一個項目(包括webpack的配置等)這無疑是浪費時間的並且都最後仍是是而非的。因此我以爲徹底能夠用腳手架建一個webpack項目,而後咱們能夠具體對應它生成的文件學習(固然這只是個人學習方法,我認爲這樣比較好學,但不必定人人都是這樣的)。
在學習的過程當中發現網上許多的簡介都已通過期(vue發展的過快了吧。。。。),因此我結合本身的項目和網上的資料備註一下,但願和其餘的人一塊兒討論。這個適合的版本爲:nodejs(6.10.2)、vue(2.5.2)、vue-router(3.0.1)和webpack(3.6.0)的。適合的環境爲windows的,其餘的系統我也不知道可不能夠用。css


1、vue-cli安裝、webpack項目新建

一、默認電腦已經安裝了node,不會的請百度而後先安裝nodejs。
二、安裝好nodejs以後,全局安裝vue-cli:npm install -g vue-cli。
三、新建webpack項目:vue init webpack projectname(這是比較完整的,咱們學習用這個比較好)、vue init webpack-simple projectname(簡易版的)。
注意:projectname項目名不能用中文。
四、「vue init webpack-simple projectname」建立新項目的目錄結構:
生成新項目時並無安裝依賴,須要進入新的項目安裝依賴:cd projectname -> npm install。
新建項目時,會須要填一些東西,但若是你都不想填也無所謂,所有默認、所有yes都行:
(1)、Project name:——項目名稱
(2)、Project description:——項目描述
(3)、Author:——做者
(4)、Vue build:——構建模式,通常默認選擇第一種
(5)、Install vue-router?:——是否安裝引入vue-router,這裏選是,vue-router是路由組件,後面構建項目會用到
(6)、Use ESLint to lint your code?:——eslint的格式驗證很是嚴格,多一個空格少一個空格都會報錯。我的以爲若是是平時練習的話能夠選yes由於這個能夠規範本身js代碼的書寫規範。但在實際開發項目中不建議使用,會影響開發效率。
(7)、Setup unit tests with Karma + Mocha 以及Setup e2e tests with Nightwatch這兩個是測試,能夠不用安裝。
圖片描述html

「vue init webpack projectname」建立新項目的目錄結構:
圖片描述vue

圖片描述


2、build目錄下配置文件之check-versions.js

這個文件並非十分重要,只要稍微瞭解就好了。node

/**
 * 驗證版本
 */
'use strict'
//chalk是一個顏色插件。能夠經過
const chalk = require('chalk')
//semver一個版本控制插件
const semver = require('semver')
const packageConfig = require('../package.json')
//shelljss是nodejs對與多進程的支持,是對於child_process封裝
const shell = require('shelljs')

function exec (cmd) {
  return require('child_process').execSync(cmd).toString().trim()
}

const versionRequirements = [
  {//對應node的版本
    name: 'node',
    //當前環境版本,semver.clean把當前環境版本信息轉化規定格式,也是'  =v1.2.3  '->'1.2.3'
    currentVersion: semver.clean(process.version),
    //要求版本,對應package.json的engines所配置的信息
    versionRequirement: packageConfig.engines.node
  }
]

//npm環境中
if (shell.which('npm')) {
  versionRequirements.push({
    name: 'npm',
    //執行方法獲得版本號
    currentVersion: exec('npm --version'),
    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)
  }
}

3、build目錄下配置文件之utils.js

這個文件主要用於處理有關於css方面的,主要對後面vue-loader.conf.js文件有關係,對webpack配置loaders方面也有影響。webpack

/**
 * webpack開發環境:主要用來處理css-loader和vue-style-loader
 */

'use strict'
const path = require('path')
const config = require('../config')
//引入extract-text-webpack-plugin插件,用來將css提取到單獨的css文件中
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const packageConfig = require('../package.json')

exports.assetsPath = function (_path) {
  //process.env.NODE_ENV在bulid.js中定義
  //若是爲生產環境assetsSubDirectory爲「static」,不然也爲「static」
  //config.build.assetsSubDirectory與config.dev.assetsSubDirectory都在config/index中定義
  const assetsSubDirectory = process.env.NODE_ENV === 'production'
    ? config.build.assetsSubDirectory
    : config.dev.assetsSubDirectory

  //path.join和path.posix.join區別前者返回完整路徑,後者返回完整路徑的相對路徑
  //例:path.join是E:/shishans/blogsss/static,path.posix.join是static
  return path.posix.join(assetsSubDirectory, _path)
}

exports.cssLoaders = function (options) {
  options = options || {}

  //css-loader的基本配置
  const cssLoader = {
    loader: 'css-loader',
    options: {
      //option用於配置loder的
      //是否開啓cssMap,默認是false
      //通常咱們會壓縮js或者css以節省寬帶,但在開發壓縮就很難調試
      //因此用sourceMap進行關聯,給出對應的sourceMap文件
      sourceMap: options.sourceMap
    }
  }

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

  // generate loader string to be used with extract text plugin
  function generateLoaders (loader, loaderOptions) {
    //將上面的基礎配置放到一個數據中
    const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
    //若是該函數傳遞了單獨的loder就加入到loaders數組中例如:sass或者less之類的
    if (loader) {
      loaders.push({
        //加載對應的loader
        loader: loader + '-loader',
        //es6方法Object.assign:主要用於合併對象的,淺拷貝
        options: Object.assign({}, loaderOptions, {
          sourceMap: options.sourceMap
        })
      })
    }

    // Extract CSS when that option is specified
    // (which is the case during production build)
    // extract自定義屬性,用ExtractTextPlugin.extract控制是否把文件單獨提取
    // true:單獨提取,false表示不提取
    if (options.extract) {
      return ExtractTextPlugin.extract({
        use: loaders,
        fallback: 'vue-style-loader'
      })
    } else {
      //[].concat()方法用於鏈接數組
      return ['vue-style-loader'].concat(loaders)
    }
  }

  // https://vue-loader.vuejs.org/en/configurations/extract-css.html
  return {
    css: generateLoaders(),//返回[cssLoader, vue-style-loader]
    postcss: generateLoaders(),//返回[cssLoader, vue-style-loader]
    less: generateLoaders('less'),//返回[cssLoader, vue-style-loader, less]
    sass: generateLoaders('sass', { indentedSyntax: true }),
    scss: generateLoaders('sass'),
    stylus: generateLoaders('stylus'),
    styl: generateLoaders('stylus')
  }
}

// Generate loaders for standalone style files (outside of .vue)
// 這個方法主要處理import這種方式導入的文件類型的打包
exports.styleLoaders = function (options) {
  const output = []
  const loaders = exports.cssLoaders(options)

  for (const extension in loaders) {
    const loader = loaders[extension]
    output.push({
      test: new RegExp('\\.' + extension + '$'),
      use: loader
    })
  }

  return output
}

//用於返回腳手架錯誤的函數
exports.createNotifierCallback = () => {
  //使用node-notifier來發送桌面消息,包括應用狀態改變以及錯誤信息
  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')
    })
  }
}

4、build目錄下配置文件之webpack.base.conf.js

從這個文件開始,webpack配置文件正式開始,前面的至關因而這個文件參數般的存在。而實際上這個也不是正式會運行的配置文件。一個項目有2中狀況:開發環境和生成環境。這2中環境一些方面的配置是不同的,好比在生產環境咱們會對js和css進行壓縮以減小寬帶。這個文件其實是這2中環境通用的配置。下面的webpack.dev.conf.js文件(開發環境)、webpack.prod.conf.js(生產環境),這2個文件纔是實際環境運行使用的配置文件。git

/**
 * webpack開發環境和生成環境通用的配置
 */

'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')

//獲取對應文件路徑的函數
//由於該文件是在項目的二級文件build下,因此要加上../這樣才能找到像src這樣的目錄
function resolve (dir) {
  //join方法用於將多個字符串結合成一個路徑字符串
  //path在node中會常常用到能夠仔細瞭解一下path的各類方法
  //__dirname:獲取當前文件所在目錄的完整絕對路徑
  return path.join(__dirname, '..', dir)
}

//eslint用來檢查咱們寫的js代碼是否知足指定的規則
const createLintingRule = () => ({
  test: /\.(js|vue)$/,
  loader: 'eslint-loader',
  enforce: 'pre',
  include: [resolve('src'), resolve('test')],
  options: {
    formatter: require('eslint-friendly-formatter'),
    emitWarning: !config.dev.showEslintErrorsInOverlay
  }
})

module.exports = {
  context: path.resolve(__dirname, '../'),
  entry: {
    //入口文件是src下的main.js
    app: './src/main.js'
  },
  output: {
    path: config.build.assetsRoot,
    filename: '[name].js',
    publicPath: process.env.NODE_ENV === 'production'
      ? config.build.assetsPublicPath
      : config.dev.assetsPublicPath
  },
  resolve: {
    //自動解析肯定的擴展,在引入模塊時不帶擴展名
    //例如:import somejs from "@/some"
    extensions: ['.js', '.vue', '.json'],
    alias: {
      // 後面的$符號指精確匹配
      // 也就是說只能使用 import vuejs from "vue" 這樣的方式導入vue.esm.js文件
      'vue$': 'vue/dist/vue.esm.js',
      // resolve('src') 其實在這裏就是項目根目錄中的src目錄
      // 例如引用src目錄下的some.js方法:import somejs from "@/some.js"
      // 用@來代替../src
      '@': resolve('src'),
    }
  },
  module: {
    rules: [
      ...(config.dev.useEslint ? [createLintingRule()] : []),
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: vueLoaderConfig
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
      },
      {
        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]')
        }
      }
    ]
  },
  node: {
    // prevent webpack from injecting useless setImmediate polyfill because Vue
    // source contains it (although only uses it if it's native).
    setImmediate: false,
    // prevent webpack from injecting mocks to Node native modules
    // that does not make sense for the client
    dgram: 'empty',
    fs: 'empty',
    net: 'empty',
    tls: 'empty',
    child_process: 'empty'
  }
}

5、build目錄下配置文件之webpack.dev.conf.js

webpack.prod.conf.js也差很少。這2者之間的差異之後再討論。es6

/**
 * 此文件用於開發環境下的webpack配置
 * 就本項目執行npm run dev 和 npm run start都會用到這個文件的配置
 * 具體能夠參考JavaScript中"scripts"的配置
 */
'use strict'
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const path = require('path')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
//生成html文件
const HtmlWebpackPlugin = require('html-webpack-plugin')
//friendly-errors-webpack-plugin:把webpack的錯誤和日誌蒐集起來展示給用戶
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const portfinder = require('portfinder')

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 })
  },
  // cheap-module-eval-source-map is faster for development
  // devtool是開發工具選項,用來指定如何生成sourcemap文件,cheap-module-eval-source-map此款soucemap文件性價比最高
  // 生產環境:#source-map
  // 開發環境:#cheap-module-eval-source-map  編譯消耗小
  devtool: config.dev.devtool,

  // these devServer options should be customized in /config/index.js
  devServer: {
    clientLogLevel: 'warning',
    historyApiFallback: {
      rewrites: [
        { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
      ],
    },
    hot: true,
    contentBase: false, // since we use CopyWebpackPlugin.
    compress: true,
    host: HOST || config.dev.host,
    port: PORT || config.dev.port,
    open: config.dev.autoOpenBrowser,
    overlay: config.dev.errorOverlay
      ? { warnings: false, errors: true }
      : false,
    publicPath: config.dev.assetsPublicPath,
    proxy: config.dev.proxyTable,
    quiet: true, // necessary for FriendlyErrorsPlugin
    watchOptions: {
      poll: config.dev.poll,
    }
  },
  plugins: [
    // DefinePlugin內置webpack插件,專門用來定義全局變量的
    // 下面定義一個全局變量 process.env 而且值是以下
    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(),
    // https://github.com/ampedandwired/html-webpack-plugin
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'index.html',
      inject: true
    }),
    // copy custom static assets
    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 {
      // publish the new Port, necessary for e2e tests
      process.env.PORT = port
      // add port to devServer config
      devWebpackConfig.devServer.port = port

      // Add FriendlyErrorsPlugin
      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)
    }
  })
})

6、config目錄下之index.js

這個文件配置了一些全局屬性,分別dev和build用於區別開發環境和生產環境不一樣的地方。github


7、總結

在vue2.5.2中取消了build目錄中的dev-server.js和dev-client.js文件,改用webpack.dev.conf.js代替,因此 配置本地訪問在webpack.dev.conf.js裏配置便可。具體如何配置之後運用到時候具體瞭解,本文章就不講了。
本文章只是簡單地理解一下webpack的配置文件,其中用到的各類插件和插件使用方面都沒有涉及。web


8、參考的網址

雖然這裏一些網址的東西與vue2.5的不一樣,可是十分有用的。
一、https://segmentfault.com/a/11...
二、http://www.jb51.net/article/1...
三、https://segmentfault.com/a/11...
四、https://segmentfault.com/a/11...vue-router

相關文章
相關標籤/搜索