使用vue-cli快速建立的vue項目目錄以下:css
build文件夾下的文件目錄以下:html
config文件夾下的文件目錄以下:前端
代碼規範化編輯能夠幫助咱們簡單整潔的展現代碼結構,而.editorconfig文件就是對代碼規範設置的一個文檔。使用編輯器/IDE打開項目時編輯器會自動尋找.editorconfig文件,而後根據其內容配置去顯示相關的項目代碼文件。vue
項目頁面入口(可刪除),一般是進行根節點功能設置,如須要引用靜態資源文件夾static中的文件時,建議在index.html中進行引入;手機端文件在此文件中更改viewport等。node
app.vue時項目的主組件,全部頁面都是在app.vue下切換的(基於此組件,若多頁面的則不是)。其中<router-view/>是子路由視圖。webpack
main.js是入口文件,主要做用是初始化vue實例並使用須要的插件。使用某些插件使用Vue.use(xxx)。ios
路由配置文件,地址爲src>router>index.js。可進行自定義配置,而後引入到main.js中,加入至vue實例。git
本身增長文件,做用爲數據倉庫,對項目中公用數據進行設置存儲。github
詳見:VUE 數據請求和響應(axios)web
webpack是當下最熱門的前端資源模塊化管理工具和打包工具,能夠將不少鬆散的模塊按照必定的規則打包成符合生產環境的前端資源,同時具備按需加載,等到實際須要的時候進行異步加載。經過loader的轉換,在項目中任何形式的資源均可以被理解爲模塊,好比img,css,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' } }
module: { // 經過傳入一些配置來獲取rules配置,此處都爲true,表示都生成 rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true }) }
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') } }
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: ['.*'] } ]) ]
生產環境下的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: [] })
module主要是針對css的處理,調用了utils.styleLoaders
module: { rules: utils.styleLoaders({ sourceMap: config.build.productionSourceMap, extract: true, usePostCSS: true }) }
輸出文件的文件目錄/文件名等的設置
output: { path: config.build.assetsRoot,//導出文件目錄 filename: utils.assetsPath('js/[name].[chunkhash].js'), //導出的文件名 chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')//非入口文件的文件名,而又須要被打包出來的文件命名配置,如按需加載的模塊 }
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: ['.*']//忽視.*文件 } ]) ]
// 配置文件開啓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()) }