github地址(內(nèi)含簡單例子)

使用技術(shù)棧

  • webpack(^2.6.1)

  • webpack-dev-server(^2.4.5)

  • vue(^2.3.3)

  • vuex(^2.3.1)

  • vue-router(^2.5.3)

  • vue-loader(^12.2.1)

  • eslint(^3.19.0)

需要學(xué)習(xí)的知識

vue.js 
vuex 
vue-router 
vue-loader 
webpack2 
eslint 


內(nèi)容相當(dāng)多,尤其是webpack2教程,官方腳手架vue-cli雖然相當(dāng)完整齊全,但是修改起來還是挺花時間,于是自己參照網(wǎng)上的資料和之前做過的項目用到的構(gòu)建工具地去寫了一個簡單vue項目腳手架。適用于多頁面spa模式的業(yè)務(wù)場景(每個模塊都是一個spa)。比較簡單,主要就是一個webpack.config.js文件,沒有說特意地去劃分成分webpack.dev.config.js、webpack.prov.config.js等等。下面是整個webpack.config.js文件代碼:

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

  1 const { resolve } = require('path')  2 const webpack = require('webpack')  3 const HtmlWebpackPlugin = require('html-webpack-plugin')  4 const ExtractTextPlugin = require('extract-text-webpack-plugin')  5 const glob = require('glob')  6   7 module.exports = (options = {}) => {  8     // 配置文件,根據(jù) run script不同的config參數(shù)來調(diào)用不同config  9     const config = require('./config/' + (process.env.npm_config_config || options.config || 'dev')) 10     // 遍歷入口文件,這里入口文件與模板文件名字保持一致,保證能同時合成HtmlWebpackPlugin數(shù)組和入口文件數(shù)組 11     const entries = glob.sync('./src/modules/*.js') 12     const entryJsList = {} 13     const entryHtmlList = [] 14     for (const path of entries) { 15         const chunkName = path.slice('./src/modules/'.length, -'.js'.length) 16         entryJsList[chunkName] = path 17         entryHtmlList.push(new HtmlWebpackPlugin({ 18             template: path.replace('.js', '.html'), 19             filename: 'modules/' + chunkName + '.html', 20             chunks: ['manifest', 'vendor', chunkName] 21         })) 22     } 23     // 處理開發(fā)環(huán)境和生產(chǎn)環(huán)境ExtractTextPlugin的使用情況 24     function cssLoaders(loader, opt) { 25         const loaders = loader.split('!') 26         const opts = opt || {} 27         if (options.dev) { 28             if (opts.extract) { 29                 return loader 30             } else { 31                 return loaders 32             } 33         } else { 34             const fallbackLoader = loaders.shift() 35             return ExtractTextPlugin.extract({ 36                 use: loaders, 37                 fallback: fallbackLoader 38             }) 39         } 40     } 41  42     const webpackObj = { 43         entry: Object.assign({ 44             vendor: ['vue', 'vuex', 'vue-router'] 45         }, entryJsList), 46         // 文件內(nèi)容生成哈希值chunkhash,使用hash會更新所有文件 47         output: { 48             path: resolve(__dirname, 'dist'), 49             filename: options.dev ? 'static/js/[name].js' : 'static/js/[name].[chunkhash].js', 50             chunkFilename: 'static/js/[id].[chunkhash].js', 51             publicPath: config.publicPath 52         }, 53  54         externals: { 55  56         }, 57  58         module: { 59             rules: [ 60                 // 只 lint 本地 *.vue 文件,需要安裝eslint-plugin-html,并配置eslintConfig(package.json) 61                 { 62                     enforce: 'pre', 63                     test: /.vue$/, 64                     loader: 'eslint-loader', 65                     exclude: /node_modules/ 66                 }, 67                 /* 68                     http://blog.guowenfh.com/2016/08/07/ESLint-Rules/ 69                     http://eslint.cn/docs/user-guide/configuring 70                     [eslint資料] 71                  */ 72                 { 73                     test: /\.js$/, 74                     exclude: /node_modules/, 75                     use: ['babel-loader', 'eslint-loader'] 76                 }, 77                 // 需要安裝vue-template-compiler,不然編譯報錯 78                 { 79                     test: /\.vue$/, 80                     loader: 'vue-loader', 81                     options: { 82                         loaders: { 83                             sass: cssLoaders('vue-style-loader!css-loader!sass-loader', { extract: true }) 84                         } 85                     } 86                 }, 87                 { 88                     // 需要有相應(yīng)的css-loader,因為第三方庫可能會有文件 89                     // (如:element-ui) css在node_moudle 90                     // 生產(chǎn)環(huán)境才需要code抽離,不然的話,會使熱重載失效 91                     test: /\.css$/, 92                     use: cssLoaders('style-loader!css-loader') 93                 }, 94                 { 95                     test: /\.(scss|sass)$/, 96                     use: cssLoaders('style-loader!css-loader!sass-loader') 97                 }, 98                 { 99                     test: /\.(png|jpg|jpeg|gif|eot|ttf|woff|woff2|svg|svgz)(\?.+)?$/,100                     use: [101                         {102                             loader: 'url-loader',103                             options: {104                                 limit: 10000,105                                 name: 'static/imgs/[name].[ext]?[hash]'106                             }107                         }108                     ]109                 }110             ]111         },112 113         plugins: [114             ...entryHtmlList,115             // 抽離css116             new ExtractTextPlugin({117                 filename: 'static/css/[name].[chunkhash].css',118                 allChunks: true119             }),120             // 抽離公共代碼121             new webpack.optimize.CommonsChunkPlugin({122                 names: ['vendor', 'manifest']123             }),124             // 定義全局常量125             // cli命令行使用process.env.NODE_ENV不如期望效果,使用不了,所以需要使用DefinePlugin插件定義,定義形式'"development"'或JSON.stringify('development')126             new webpack.DefinePlugin({127                 'process.env': {128                     NODE_ENV: options.dev ? JSON.stringify('development') : JSON.stringify('production')129                 }130             })131 132         ],133 134         resolve: {135             // require時省略的擴(kuò)展名,不再需要強(qiáng)制轉(zhuǎn)入一個空字符串,如:require('module') 不需要module.js136             extensions: ['.js', '.json', '.vue', '.scss', '.css'],137             // require路徑簡化138             alias: {139                 '~': resolve(__dirname, 'src'),140                 // Vue 最早會打包生成三個文件,一個是 runtime only 的文件 vue.common.js,一個是 compiler only 的文件 compiler.js,一個是 runtime + compiler 的文件 vue.js。141                 // vue.js = vue.common.js + compiler.js,默認(rèn)package.json的main是指向vue.common.js,而template 屬性的使用一定要用compiler.js,因此需要在alias改變vue指向142                 vue: 'vue/dist/vue'143             },144             // 指定import從哪個目錄開始查找145             modules: [146                 resolve(__dirname, 'src'),147                 'node_modules'148             ]149         },150         // 開啟http服務(wù),publicPath => 需要與Output保持一致 || proxy => 反向代理 || port => 端口號151         devServer: config.devServer ? {152             port: config.devServer.port,153             proxy: config.devServer.proxy,154             publicPath: config.publicPath,155             stats: { colors: true }156         } : undefined,157         // 屏蔽文件超過限制大小的warn158         performance: {159             hints: options.dev ? false : 'warning'160         },161         // 生成devtool,保證在瀏覽器可以看到源代碼,生產(chǎn)環(huán)境設(shè)為false162         devtool: 'inline-source-map'163     }164 165     if (!options.dev) {166         webpackObj.devtool = false167         webpackObj.plugins = (webpackObj.plugins || []).concat([168             // 壓縮js169             new webpack.optimize.UglifyJsPlugin({170                 // webpack2,默認(rèn)為true,可以不用設(shè)置171                 compress: {172                     warnings: false173                 }174             }),175             //  壓縮 loaders176             new webpack.LoaderOptionsPlugin({177                 minimize: true178             })179         ])180     }181 182     return webpackObj183 }

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

 

上面的代碼對于每個配置項都有注釋說明,這里有幾點需要注意的:

1. webpack.config.js導(dǎo)出的是一個function

之前項目的webpack.config.js是以對象形式export的,如下

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

1 module.exports = {2     entry: ...,3     output: {4         ...5     },6     ...7 }

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

而現(xiàn)在倒出來的是一個function,如下:

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

1 module.exports = (options = {}) => { 
2     return {3         entry: ...,4         output: {5             ...6         },7         ...8     }9 }

Android培訓(xùn),安卓培訓(xùn),手機(jī)開發(fā)培訓(xùn),移動開發(fā)培訓(xùn),云培訓(xùn)培訓(xùn)

這樣的話,function會在執(zhí)行webpack CLI的時候獲取webpack的參數(shù),通過options傳進(jìn)function,看一下package.json:

1     "local": "npm run dev --config=local",2     "dev": "webpack-dev-server -d --hot --inline --env.dev --env.config dev",3     "build": "rimraf dist && webpack -p --env.config prod" //rimraf清空dist目錄

對于local命令,我們執(zhí)行的是dev命令,但是在最后面會--config=local,這是配置,這樣我們可以通過process.env.npm_config_config獲取到,而對于dev命令,對于--env XXX,我們便可以在function獲取option.config= 'dev' 和 option.dev= true的值,特別方便!以此便可以同步參數(shù)來加載不同的配置文件了。對于-d、-p不清楚的話,可以這里查看,很詳細(xì)!

1     // 配置文件,根據(jù) run script不同的config參數(shù)來調(diào)用不同config2     const config = require('./config/' + (process.env.npm_config_config || options.config || 'dev'))
http://www.cnblogs.com/wuxiaobin/p/6970233.html