VUE (vue-cli)腳手架項目說明

1. 概述

1.1 說明

  使用vue-cli快速建立的vue項目目錄以下:css

    • build  -- webpack相關配置以及服務啓動文件,配置多依賴於下邊的config文件夾中內容
    • config -- vue基本配置文件,如監聽端口,打包輸出等配置
    • node_modules -- 安裝依賴包的目錄文件
    • src -- 頁面以及業務邏輯文件夾,在此文件夾下進行項目開發
    • static -- 靜態資源,可存放一些不須要進行打包的資源文件
    • .babelrc -- ES6語法編譯配置,用來將ES6代碼轉換爲瀏覽器識別的代碼(ES6轉ES5)
    • .editorconfig -- 代碼規範化配置文件
    • .gitignore -- git上傳須要忽略的文件格式
    • .postcssrc.js -- 轉換css工具,用js來處理css
    • index.html -- 頁面入口
    • package.json -- 項目基本信息,項目開發所需的模塊,項目名稱,版本等
    • readme.txt -- 項目說明,說明一下此項目做何使用等。

    

1.2 build

  build文件夾下的文件目錄以下:html

    • build.js -- 生產環境構建代碼
    • check-versions.js -- 檢查node,npm等版本
    • logo.png
    • utils.js -- 構建工具相關
    • vue-loader.conf.js -- css加載器配置
    • webpack.base.conf.js -- webpack基礎配置文件
    • webpack.dev.conf.js -- webpack開發環境配置文件
    • webpack.prod.conf.js -- webpack生產環境配置文件

    

1.3 config

  config文件夾下的文件目錄以下:前端

    • dev.env.js -- 開發環境變量
    • index.js -- 項目的一些配置變量
    • prod.env.js -- 生產環境變量

  

1.4 .editorconfig

  代碼規範化編輯能夠幫助咱們簡單整潔的展現代碼結構,而.editorconfig文件就是對代碼規範設置的一個文檔。使用編輯器/IDE打開項目時編輯器會自動尋找.editorconfig文件,而後根據其內容配置去顯示相關的項目代碼文件。vue

  

 

2. 項目頁面開發

2.1 index.html

  項目頁面入口(可刪除),一般是進行根節點功能設置,如須要引用靜態資源文件夾static中的文件時,建議在index.html中進行引入;手機端文件在此文件中更改viewport等。node

   

2.2 App.vue

  app.vue時項目的主組件,全部頁面都是在app.vue下切換的(基於此組件,若多頁面的則不是)。其中<router-view/>是子路由視圖。webpack

  

2.3  main.js

  main.js是入口文件,主要做用是初始化vue實例並使用須要的插件。使用某些插件使用Vue.use(xxx)。ios

  

2.4  router

  路由配置文件,地址爲src>router>index.js。可進行自定義配置,而後引入到main.js中,加入至vue實例。git

  

 2.5 store(vuex)

  本身增長文件,做用爲數據倉庫,對項目中公用數據進行設置存儲。github

  

 2.6 http.js(axios)

 詳見:VUE 數據請求和響應(axios)web

3. webpack

   webpack是當下最熱門的前端資源模塊化管理工具和打包工具,能夠將不少鬆散的模塊按照必定的規則打包成符合生產環境的前端資源,同時具備按需加載,等到實際須要的時候進行異步加載。經過loader的轉換,在項目中任何形式的資源均可以被理解爲模塊,好比img,css,js等。

 3.1 webpack.base.conf.js

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

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

module.exports = {
  context: path.resolve(__dirname, '../'),
  //******入口******
  entry: {
    app: './src/main.js'
  },
  //輸出文件,打包到哪裏,配置來源於config文件夾配置
  output: {
    //config>index.js下的build中的assetsRoot,即dist文件夾
    path: config.build.assetsRoot,
    //導出文件的文件名
    filename: '[name].js',
    //生產模式或開發模式下的html,js等文件內部引用的公共路徑(config>index.js下的build或dev)
    publicPath: process.env.NODE_ENV === 'production'
      ? config.build.assetsPublicPath
      : config.dev.assetsPublicPath
  },
  //文件解析
  resolve: {
    //自動解析肯定的擴展名,使導入模塊時不帶擴展名(import a from a.vue,後綴名省略)
    extensions: ['.js', '.vue', '.json'],
    alias: {
      // 建立import 或 require的別名
      'vue$': 'vue/dist/vue.esm.js',
      // 用@來代替src,引用路徑時使用
      '@': resolve('src'),
    }
  },
  //項目中不一樣類型的模塊處理規則
  module: {
    rules: [
      {
        test: /\.vue$/,//vue 文件後綴
        loader: 'vue-loader',//使用vue-loader進行處理
        options: vueLoaderConfig//對vue-loader作的額外選項配置
      },
      {
        test: /\.js$/,//js文件後綴
        loader: 'babel-loader',// 使用babel-loader進行處理
        // 必須處理包含src test的文件夾
        include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
      },
      {
        test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,//圖片後綴
        loader: 'url-loader',//使用url-loader處理
        //對loader作的額外配置
        options: {
          limit: 10000,//小於10kb的以base64進行引用
          // 文件名爲name ,7位hash值,擴展名
          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'
  }
}

 3.2 開發環境相關

3.2.1 webpack.dev.conf.js

  module: {
    // 經過傳入一些配置來獲取rules配置,此處都爲true,表示都生成
    rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
  }

3.2.2 styleLoaders/cssLoader(until.js)

  styleLoader配置:

exports.styleLoaders = function (options) {
  const output = [];//返回數組,數組中保存的是針對各類類型的樣式文件的處理方式
  // 調用cssLoaders方法返回各種型的樣式對象(css:loader)
  const loaders = exports.cssLoaders(options);
  // 遍歷loaders
  for (const extension in loaders) {
    //根據遍歷得到的key(extension) 來獲得value (loader)
    const loader = loaders[extension]
    output.push({
      test: new RegExp('\\.' + extension + '$'),//處理文件的類型
      use: loader// 用loader來處理,loader來自loaders【extension】
    })
  }

  return output
}

  cssLoaders配置:

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

  const cssLoader = {
    loader: 'css-loader',
    // options 是 css-loader的選項配置
    options: {
      sourceMap: options.sourceMap// 根據參數是否要生成sourceMap文件
    }
  }

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

  // generate loader string to be used with extract text plugin 生成loader
  function generateLoaders (loader, loaderOptions) {
    // 默認的loader是css-loader
    const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]

    if (loader) {
      loaders.push({
        loader: loader + '-loader',
        // 將loaderOptions和sourceMap組成一個對象
        options: Object.assign({}, loaderOptions, {
          sourceMap: options.sourceMap
        })
      })
    }

    // Extract CSS when that option is specified
    // (which is the case during production build)
    if (options.extract) {
      // ExtractTextPlugin 分離js中引入的css文件
      return ExtractTextPlugin.extract({
        use: loaders,// 處理loader
        fallback: 'vue-style-loader'// 沒有被提取分離時使用的loader
      })
    } else {
      return ['vue-style-loader'].concat(loaders)
    }
  }

  // https://vue-loader.vuejs.org/en/configurations/extract-css.html
  //返回css類型對應的loader組成的對象  generateLoaders()來生成loader
  return {
    css: generateLoaders(),
    postcss: generateLoaders(),
    less: generateLoaders('less'),
    sass: generateLoaders('sass', { indentedSyntax: true }),
    scss: generateLoaders('sass'),
    stylus: generateLoaders('stylus'),
    styl: generateLoaders('stylus')
  }
}

3.2.3 plugins

  webpack.dev.conf.js下的plugins。

  plugins: [
    //定義全局變量
    new webpack.DefinePlugin({
      'process.env': require('../config/dev.env')
    }),
    // 熱更新插件
    new webpack.HotModuleReplacementPlugin(),
    //在熱加載時直接返回更新文件名,而不是文件的id。
    new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
    // 不觸發錯誤,即編譯後運行的包正常運行
    new webpack.NoEmitOnErrorsPlugin(),
    // https://github.com/ampedandwired/html-webpack-plugin
    // 自動生成html文件,好比編譯後文件的引用
    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: ['.*']
      }
    ])
  ]

 3.3 生產環境相關

3.3.1 webpack.prod.conf.js

  生產環境下的webpack配置,經過merge方法合併webpack.base.conf.js基礎配置。

const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')

const webpackConfig = merge(baseWebpackConfig, {
  module: {
  },
  devtool: false,
  output: {},
  plugins: []
})

3.3.2 webpack.prod.conf.js——module

  module主要是針對css的處理,調用了utils.styleLoaders

  module: {
    rules: utils.styleLoaders({
      sourceMap: config.build.productionSourceMap,
      extract: true,
      usePostCSS: true
    })
  }

3.3.3 webpack.prod.conf.js——output

  輸出文件的文件目錄/文件名等的設置

  output: {
    path: config.build.assetsRoot,//導出文件目錄
    filename: utils.assetsPath('js/[name].[chunkhash].js'), //導出的文件名 
    chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')//非入口文件的文件名,而又須要被打包出來的文件命名配置,如按需加載的模塊 
  }

3.3.4 webpack.prod.conf.js——plugins(插件)

plugins: [
    // http://vuejs.github.io/vue-loader/en/workflow/production.html
    new webpack.DefinePlugin({
      'process.env': env// 配置全局環境爲生產環境
    }),
    // js壓縮插件
    new UglifyJsPlugin({
      uglifyOptions: {
        // 壓縮配置
        compress: {
          warnings: false//不顯示警告
        }
      },
      sourceMap: config.build.productionSourceMap,// 是否生成sourceMap文件
      parallel: true
    }),
    // extract css into its own file 將js中引入css分離插件
    new ExtractTextPlugin({
      filename: utils.assetsPath('css/[name].[contenthash].css'),// 分離出來的css文件名
      allChunks: true,
    }),
    // 壓縮提取出的css,並解決ExtractTextPlugin分離出的js重複問題(多個文件引用同一個css文件)
    new OptimizeCSSPlugin({
      cssProcessorOptions: config.build.productionSourceMap
        ? { safe: true, map: { inline: false } }
        : { safe: true }
    }),
    //生成html的插件,引入css文件和js文件
    new HtmlWebpackPlugin({
      filename: config.build.index,// 生成的html的文件名
      template: 'index.html',// 依據的模板
      inject: true,// 注入的js文件會被放在Body標籤中,當值爲'head'的時候,將被放在head標籤中
      // 壓縮配置
      minify: {
        removeComments: true,// 刪除html中的註釋代碼
        collapseWhitespace: true,// 刪除html中的空白符
        removeAttributeQuotes: true// 刪除html元素中屬性的引號
        // more options:
        // https://github.com/kangax/html-minifier#options-quick-reference
      },
      // necessary to consistently work with multiple chunks via CommonsChunkPlugin
      chunksSortMode: 'dependency'//按dependency的順序引入
    }),
    // keep module.id stable when vendor modules does not change
    new webpack.HashedModuleIdsPlugin(),
    // enable scope hoisting
    new webpack.optimize.ModuleConcatenationPlugin(),
    // 分離公共js到vendor中
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',// 文件名
      minChunks (module) {
        // 聲明公告的模塊來自 node_modules文件夾
        return (
          module.resource &&
          /\.js$/.test(module.resource) &&
          module.resource.indexOf(
            path.join(__dirname, '../node_modules')
          ) === 0
        )
      }
    }),

    //將運行時代碼提取到單獨的manifest文件中,防止影響vendor.js
    new webpack.optimize.CommonsChunkPlugin({
      name: 'manifest',
      minChunks: Infinity
    }),
    // This instance extracts shared chunks from code splitted chunks and bundles them
    // in a separate chunk, similar to the vendor chunk
    // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
    new webpack.optimize.CommonsChunkPlugin({
      name: 'app',
      async: 'vendor-async',
      children: true,
      minChunks: 3
    }),

    // 複製靜態資源,將static文件內的內容複製到指定文件夾
    new CopyWebpackPlugin([
      {
        from: path.resolve(__dirname, '../static'),
        to: config.build.assetsSubDirectory,
        ignore: ['.*']//忽視.*文件
      }
    ])
  ]

3.3.5 webpack.prod.conf.js——額外配置

// 配置文件開啓gzip壓縮
if (config.build.productionGzip) {
  // 引入壓縮文件的組件,該插件會對生成的文件進行壓縮,生成一個.gz文件
  const CompressionWebpackPlugin = require('compression-webpack-plugin')

  webpackConfig.plugins.push(
    new CompressionWebpackPlugin({
      asset: '[path].gz[query]',//目標文件名
      algorithm: 'gzip',//使用gzip壓縮
      // 知足正則表達式的文件會被壓縮
      test: new RegExp(
        '\\.(' +
        config.build.productionGzipExtensions.join('|') +
        ')$'
      ),
      threshold: 10240,//資源文件大於10kb的時候會被壓縮
      minRatio: 0.8//最小壓縮比達到0.8的時候會被壓縮
    })
  )
}
//打包體積優化
if (config.build.bundleAnalyzerReport) {
  const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
  webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
相關文章
相關標籤/搜索