- 新的項目組同事整了一個webpack3.*的腳手架
- (先前本身弄了一個2.0的腳手架)裏面的配置項摸索了一遍,就想看看3.*在配置文件上面update了什麼
- 工做閒時花了一點時間將配置文件中都加上了註釋,相信看了就和我同樣從不那麼太懂到有那麼一點懂了. ^^
- 平時用的blog寫這種文章十分不友好,因此記錄在這邊順便和你們一塊兒學習(時不時會update一些修正項在最後面)
- 若是有須要的朋友能夠上個人github下載,裏面還有舊的2.0版本的腳手架.github連接
- node v7.10.0
- vue v2.8.2
這裏的文件是公用的一些基礎配置項
'use strict' // 基礎配置文件 const path = require('path') const utils = require('./utils') const config = require('../config') const vueLoaderConfig = require('./vue-loader.conf') // 定義的路徑拼接方法(join直接的拼接, path.resolve等於在終端輸入路徑) function resolve (dir) { // http://nodejs.cn/api/path.html#path_path_join_paths return path.join(__dirname, '..', dir) } const entries = utils.getEntry('./src/module/*/*.js'); /* __dirname 指的是當前你這個當前文件在 硬盤文件夾全路徑 例如這個base.conf.js文件是在 build文件夾裏 那麼 __dirname = /硬盤路徑/build */ module.exports = { // 基礎目錄,絕對路徑,用於從配置中解析入口起點 context: path.resolve(__dirname, '../'), /* 起點或是應用程序的起點入口。從這個起點開始,應用程序啓動執行。若是傳遞一個數組,那麼數組的每一項都會執行。 若是是多入口的狀況 entry: { home: "./home.js", about: "./about.js", contact: "./contact.js" } 入口對象的key值是結合dev.conf.js中的HtmlWebpackPlugin 做爲url訪問的路徑 例如 entry: { home: "./home.js" } 訪問路徑:localhost:port/home.html entry: { fgh/home: './home.js' } 訪問路徑:localhost:port/fgh/home.html */ entry: entries, // 輸出 output: { // 編譯輸出的靜態資源根路徑 path: config.build.assetsRoot, // 此選項決定了每一個輸出 bundle 的名稱。 // [name]是指入口名稱 [id]是指chunk id [hash]是指構建完的hash [chunkhash]是指每一個內容的hash 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'), } }, /* https://doc.webpack-china.org/plugins/provide-plugin/#src/components/Sidebar/Sidebar.jsx ProvidePlugin 能夠全局加載模塊,例以下面若是想全局加載一個jq */ // plugins: [ // new webpack.ProvidePlugin({ // $: 'jquery' // }) // ], // 各類loader的配置 module: { rules: [ { test: /\.vue$/, loader: 'vue-loader', options: vueLoaderConfig }, /* 關於.babelrc的配置 部分可參考 https://segmentfault.com/a/1190000008159877 https://babeljs.cn/docs/plugins/preset-env/ https://doc.webpack-china.org/loaders/babel-loader/ 1.babel-preset-env 是指動態的require瀏覽器所缺的轉換babel插件. 這個動態是經過文件裏面的配置, "env", { //是否將模塊編譯爲 amd cmd commonjs等 "modules": false, "targets": { //指瀏覽器最新的2個版本 或者safari大於7的版本 >5%是指 市場率超過5%的瀏覽器 "browsers": ["last 2 versions", "safari >= 7"] } } 若是用了env 沒有加任何配置的話 那麼默認與 babel-preset-latest同樣 2.babel-preset-stage 有4個版本 Stage 0 - 稻草人: 只是一個想法,多是 babel 插件。 Stage 1 - 提案: 初步嘗試。 Stage 2 - 初稿: 完成初步規範。 Stage 3 - 候選: 完成規範和瀏覽器初步實現。 Stage 4(隱藏版本表示已經完成 將會在新的一版所發佈) 等同於es2015 es2016... 3.在plugin中有 babel-plugin-transform-runtime 是動態的模塊加載所需的轉換模塊 由於如文檔所說 Babel 幾乎能夠編譯全部時新的 JavaScript 語法,但對於 APIs 來講卻並不是如此。 例如: Promise、Set、Map 等新增對象,Object.assign、Object.entries等靜態方法。 --說到runtime就會提到babel-polyfill (babel-polyfill 的作法是將全局對象統統污染一遍) babel-runtime 更像是分散的 polyfill 模塊,只會在模塊裏單獨引入須要用到的api, 不會影響全局, 例子: 在模塊中 import Promise from 'babel-runtime/core/promise' 可是每一個模塊單獨這樣引入也是麻煩, 因此能夠經過配置babel-plugin-transform-runtime來簡單操做 --- 有一個小細節你們注意 api中說到, babel-plugin-transform-runtime默認是和babel-runtime捆綁出現, 前面是開發依賴,後面是生產依賴. 可是vue-cli構造出來的項目中,package.json裏面並無在生產依賴中出現babel-runtime?? 後面請教了人, 原來在node_module中 babel-plugin-transform-runtime這個包裏面的package.json裏面已經把babel-runtime加入了生產. 因此當install的時候會自動將一連串的東西都裝上!! 4.還有一個縮短build的構造時間, 在下面的babel-loader裏面去 exclude掉整個 node_modules的文件夾. 能夠縮短1半時間.. */ { 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: { // 限制300kb如下的圖片均變爲base64. 否則若是使用background-image 打包以後會找不到資源 (limit是按照字節來) limit: 307200, 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]') } } ] }, /* https://doc.webpack-china.org/configuration/node/#node 每一個屬性都是 Node.js 全局變量或模塊的名稱 true:提供 polyfill。 false: 什麼都不提供。 "empty":提供空對象。 */ 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' } }
'use strict' // 開發模式配置文件 // 引入工具集合的文件 const utils = require('./utils') const webpack = require('webpack') const config = require('../config') // 合併插件相似object.assign合併公共部分 const merge = require('webpack-merge') // node的path工具函數 const path = require('path') const baseWebpackConfig = require('./webpack.base.conf') // webpack 複製文件和文件夾的插件 const CopyWebpackPlugin = require('copy-webpack-plugin') // 自動生成 html 而且注入到 .html 文件中的插件 const HtmlWebpackPlugin = require('html-webpack-plugin') const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') // 自動檢索下一個可用端口 const portfinder = require('portfinder') /* http://nodejs.cn/api/process.html#process_process_env process.env 是在node環境中 返回一個包含用戶環境信息的對象。 ------ 這裏的p.e屬性是node環境原生的,與下面用webpack.d*去定義出來不一樣, 要改變裏面的值可參考 ./build.js 直接 process.env.NODE_ENV = 'production' ------ */ // 獲取在process.env 定義的host和port const HOST = process.env.HOST const PORT = process.env.PORT && Number(process.env.PORT) // 多頁面html路徑集合 const pages = utils.getEntry('./src/module/*/*.html'); const devWebpackConfig = merge(baseWebpackConfig, { module: { // css-loader的加工 rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true }) }, // 檢測開發環境下是否生成source map(而且生成的模式是怎麼樣) devtool: config.dev.devtool, /* https://doc.webpack-china.org/configuration/dev-server/#src/components/Sidebar/Sidebar.jsx webpack-dev-server 的配置 package.json中 "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js" --progess 將運行進度輸出到控制檯。即npm run dev 顯示module 的loading --inline 應用程序啓用內聯模式(inline mode)。 這意味着一段處理實時重載的腳本被插入到你的包(bundle)中,而且構建消息將會出如今瀏覽器控制檯 (--inline = false 關閉這種模式 那麼將不會出現修改代碼後實時刷新) */ devServer: { // 開發過程當中,可配置控制檯顯示的內容 clientLogLevel: 'warning', // History API 當遇到 404 響應時會被替代爲 index.html historyApiFallback: { rewrites: [ { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') }, ], }, /* 啓用 webpack 的模塊熱替換特性 api提到,打開了這個選項 webpack會自動加載HMR的相關內容(HotModuleReplacement),因此不須要額外的配置. -------- 與舊版的vue-cli+webpack2.0的 dev-middleware結合hot-middleware 實現相似的功能 若是你使用了 webpack-dev-middleware 而沒有使用 webpack-dev-server, 請使用 webpack-hot-middleware package 包,以在你的自定義服務或應用程序上啓用 HMR。 -------- */ hot: true, // 告訴服務器從哪裏提供內容。 contentBase: false, // since we use CopyWebpackPlugin. // 一切服務都啓用gzip 壓縮 compress: true, host: HOST || config.dev.host, port: PORT || config.dev.port, // 是否自動打開瀏覽器 // openPage這個屬性能夠配置默認打開瀏覽器的頁面 open: config.dev.autoOpenBrowser, // 是否全屏彈窗的形式顯示編譯過程當中的錯誤 overlay: config.dev.errorOverlay ? { warnings: false, errors: true } : false, // 指的是url的訪問路徑前綴 publicPath: config.dev.assetsPublicPath, // 代理 proxy: config.dev.proxyTable, // 除了初始啓動信息以外的任何內容都不會被打印到控制檯 quiet: true, // necessary for FriendlyErrorsPlugin // 與監視文件相關的控制選項。 watchOptions: { poll: config.dev.poll, } }, plugins: [ /* https://doc.webpack-china.org/plugins/define-plugin/ 容許在環境中產生一個全局變量, 例以下面'process.env', 就等於隔壁文件夾 dev.env.js export出來的內容 具體的規則看上方api 可是如下定義的變量在配置文件中去引用會報錯,只容許在服務中編寫的代碼中使用 */ new webpack.DefinePlugin({ 'process.env': require('../config/dev.env') }), /* 模塊熱替換(Hot Module Replacement 或 HMR) 當上面的 devServer中 hot:true時, 這個模塊必須存在,否則webpack會報錯. 這個模塊結合上面的hot是用於, 檢測到頁面更新,在不刷新頁面的狀況下替換內容, 若是hot: true與這個模塊均不存在, 則跟舊版本的 dev-middleware/hot-*同樣,修改即會刷新 */ new webpack.HotModuleReplacementPlugin(), // 當開啓 HMR 的時候使用該插件會顯示模塊的相對路徑,建議用於開發環境。 new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update. // 在編譯出現錯誤時,使用 NoEmitOnErrorsPlugin 來跳過輸出階段。這樣能夠確保輸出資源不會包含錯誤。 new webpack.NoEmitOnErrorsPlugin(), /* https://doc.webpack-china.org/plugins/html-webpack-plugin/#src/components/Sidebar/Sidebar.jsx 該插件將爲你生成一個HTML5文件 配置項文檔 https://github.com/jantimon/html-webpack-plugin#configuration 會結合base.conf.js設置中的 入口文件和輸出文件, 將內容根據輸出filename.生成js文件 script到當前的html種 */ // new HtmlWebpackPlugin({ // // 生成html的名稱 // filename: 'index.html', // // 生成html所需的模板路徑 // template: 'index.html', // 這個配置項指js文件插入的位置 // 選項: true body head false // true和body相同,插入body最後 // head 插入head裏面 // inject: true // }), /* https://doc.webpack-china.org/plugins/copy-webpack-plugin/#src/components/Sidebar/Sidebar.jsx 這個插件是用於複製文件和文件夾,在這裏是將靜態文件夾的內容拷貝一份在開發環境中 new CopyWebpackPlugin([patterns], options) A pattern looks like: { from: 'source', to: 'dest' } */ new CopyWebpackPlugin([ { // 拷貝的路徑 from: path.resolve(__dirname, '../static'), // 訪問的路徑 to: config.dev.assetsSubDirectory, // 忽略拷貝的內容(具體的文件名或模糊的路徑) ignore: ['.*'] } ]) ] }) for(let pathName in pages){ /* https://doc.webpack-china.org/plugins/html-webpack-plugin/#src/components/Sidebar/Sidebar.jsx */ let options = { filename: `${pathName}.html`, template: pages[pathName], inject: true, // 指定當前的html插入的模塊(若是不設定會將全部頁面的js都插入, - -) chunks: [pathName] } devWebpackConfig.plugins.push(new HtmlWebpackPlugin(options)) } 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 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) } }) })
'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') // webpack 複製文件和文件夾的插件 const CopyWebpackPlugin = require('copy-webpack-plugin') // 自動生成 html 而且注入到 .html 文件中的插件 const HtmlWebpackPlugin = require('html-webpack-plugin') // 整合css的工具 https://github.com/webpack-contrib/extract-text-webpack-plugin const ExtractTextPlugin = require('extract-text-webpack-plugin') // 壓縮提取出的css 並解決ExtractTextPlugin分離出的重複問題 const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') // 壓縮代碼 const UglifyJsPlugin = require('uglifyjs-webpack-plugin') const env = require('../config/prod.env') // 多頁面html路徑集合 const pages = utils.getEntry('./src/module/*/*.html'); const webpackConfig = merge(baseWebpackConfig, { module: { /* 在utils.js已經配置好相關對extractTextPlugin的css抽取配置.經過extract: true便可觸發 若是要觸發這個 extract 須要在plugins裏面註冊一下 */ rules: utils.styleLoaders({ sourceMap: config.build.productionSourceMap, extract: true, usePostCSS: true }) }, // 檢測生產環境下是否生成source map(而且生成的模式是怎麼樣) devtool: config.build.productionSourceMap ? config.build.devtool : false, output: { path: config.build.assetsRoot, filename: utils.assetsPath('js/[name].[chunkhash].js'), // 指的是經過CommonsChunkPlugin提取出來模塊的命名規則 chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') }, plugins: [ // http://vuejs.github.io/vue-loader/en/workflow/production.html // 定義全局變量 new webpack.DefinePlugin({ 'process.env': env }), // https://doc.webpack-china.org/plugins/uglifyjs-webpack-plugin/#src/components/Sidebar/Sidebar.jsx new UglifyJsPlugin({ // 壓縮uglify的配置 uglifyOptions: { compress: { // 壓縮後刪除沒有用到的代碼時不輸出警告 warnings: false } }, // 是否使用sourcemap作關聯 sourceMap: config.build.productionSourceMap, // 壓縮代碼中是否使用多進程進行構建 parallel: true }), // 將每一個模塊的css提取到一個文件裏面 new ExtractTextPlugin({ // 提取出來的文件名稱 filename: utils.assetsPath('css/[name].[contenthash].css'), // Setting the following option to `false` will not extract CSS from codesplit chunks. // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack. // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`, // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110 allChunks: true, }), // Compress extracted CSS. We are using this plugin so that possible // duplicated CSS from different components can be deduped. // 刪除重複的css內容 new OptimizeCSSPlugin({ cssProcessorOptions: config.build.productionSourceMap ? { safe: true, map: { inline: false } } : { safe: true } }), // generate dist index.html with correct asset hash for caching. // you can customize output by editing /index.html // see https://github.com/ampedandwired/html-webpack-plugin /* https://doc.webpack-china.org/plugins/html-webpack-plugin/#src/components/Sidebar/Sidebar.jsx */ // new HtmlWebpackPlugin({ // // 生成html的名稱 // filename: config.build.index, // template: 'index.html', // // 這個配置項指js文件插入的位置 // inject: true, // // 額外的精簡配置項 // minify: { // // 刪去html中的註釋項 // removeComments: true, // // 摺疊html中的空白字符 // collapseWhitespace: true, // // 刪去沒必要要的屬性 // removeAttributeQuotes: true // // https://github.com/kangax/html-minifier#options-quick-reference // }, // // necessary to consistently work with multiple chunks via CommonsChunkPlugin // // 控制生成的js插入位置的順序(能夠結合chunks進行選擇) // chunksSortMode: 'dependency' // }), // keep module.id stable when vendor modules does not change // 該插件會根據模塊的相對路徑生成一個四位數的hash做爲模塊id new webpack.HashedModuleIdsPlugin(), // enable scope hoisting /* https://doc.webpack-china.org/plugins/module-concatenation-plugin/#src/components/Sidebar/Sidebar.jsx webpack3.0 新特性, 從本來的每一個bundle模塊打包成多個單獨閉包去調用, 變爲如今的在一個大閉包裏面去調用各個模塊, 提高了效率 */ new webpack.optimize.ModuleConcatenationPlugin(), // split vendor js into its own file /* 提取公共模塊(將公共的import模塊 提取到一個文件中.) https://doc.webpack-china.org/plugins/commons-chunk-plugin */ new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', // 模塊被抽離出來至vendor文件中的判斷 minChunks (module) { /* 通常來說這裏的module會返回整個項目所用到的組件庫包,和import的東西 而後經過這個函數去控制一下哪一些放入vendor的文件 能夠經過具體的數值或者Boolean值來控制抽取的顆粒度. 返回true, 是會將全部的import模塊都提取, 返回false,是將重複的提取出來, 具體的數值,就會做爲調用模塊的次數 來提取, */ return ( module.resource && /\.js$/.test(module.resource) && module.resource.indexOf( path.join(__dirname, '../node_modules') ) === 0 ) } }), /* https://doc.webpack-china.org/concepts/manifest/ 當編譯器(compiler)開始執行、解析和映射應用程序時,設置好的 /src文件夾就會被打散 但會保留全部模塊的詳細要點。這個數據集合稱爲 "Manifest" 當完成打包併發送到瀏覽器時,會在運行時經過 Manifest 來解析和加載模塊。 若是不提取manifest的數據,每次build打包 上面vendor文件的hash值也會被改變,致使若是發版本, 未改變vendor的代碼由於hash改變 緩存也會被幹掉 */ new webpack.optimize.CommonsChunkPlugin({ name: 'manifest', // 傳入 `Infinity` 會立刻生成 公共獨立文件 minChunks: Infinity }), /* https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk 經過children和async屬性, 將那種又被父組件和子組件一塊兒公用的模塊抽取出來, */ // new webpack.optimize.CommonsChunkPlugin({ // name: 'app', // // (建立一個異步 公共chunk) // async: 'vendor-async', // children: true, // // (在提取以前須要至少三個子 chunk 共享這個模塊) // minChunks: 3 // }), /* https://doc.webpack-china.org/plugins/copy-webpack-plugin/#src/components/Sidebar/Sidebar.jsx 這個插件是用於複製文件和文件夾,在這裏是將靜態文件夾的內容拷貝一份在開發環境中 new CopyWebpackPlugin([patterns], options) A pattern looks like: { from: 'source', to: 'dest' } */ new CopyWebpackPlugin([ { from: path.resolve(__dirname, '../static'), to: config.build.assetsSubDirectory, // 忽略拷貝的內容(具體的文件名或模糊的路徑) ignore: ['tpl/*'] //不打包模板文件夾 } ]) ] }) // gzip壓縮 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 }) ) } // bundle分析 if (config.build.bundleAnalyzerReport) { const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin webpackConfig.plugins.push(new BundleAnalyzerPlugin()) } for(let pathName in pages){ /* https://doc.webpack-china.org/plugins/html-webpack-plugin/#src/components/Sidebar/Sidebar.jsx */ let options = {// 生成html的名稱 filename: `${pathName}.html`, template: pages[pathName], // 這個配置項指js文件插入的位置 inject: true, // 額外的精簡配置項 minify: { // 刪去html中的註釋項 removeComments: true, // 摺疊html中的空白字符 collapseWhitespace: true, // 刪去沒必要要的屬性 removeAttributeQuotes: true // https://github.com/kangax/html-minifier#options-quick-reference }, // 控制生成的js插入位置的順序(能夠結合chunks進行選擇) chunksSortMode: 'dependency' } //判斷處理的路徑是否在入口配置裏 if(pathName in webpackConfig.entry){ options.chunks = ['manifest', 'vendor', pathName]; // 加上hash值進行緩存處理 options.hash = true; } webpackConfig.plugins.push(new HtmlWebpackPlugin(options)) } module.exports = webpackConfig
'use strict' require('./check-versions')() // 在process.env加入生產標識 process.env.NODE_ENV = 'production' // loading的插件 https://github.com/sindresorhus/ora const ora = require('ora') // 能夠在 node 中執行`rm -rf`的工具 // https://github.com/isaacs/rimraf const rm = require('rimraf') const path = require('path') // 在終端輸出帶顏色的文字 // https://github.com/chalk/chalk const chalk = require('chalk') const webpack = require('webpack') const config = require('../config') //生產配置文件 const webpackConfig = require('./webpack.prod.conf') // 實例化ora loading的插件 const spinner = ora('building for production...') spinner.start() // 刪除這個文件夾 (遞歸刪除) 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, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build. 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' )) }) })
- vue-loader.conf.js 配置vue-loader的內容
- check-versions.js 顧名思義檢查版本的文件
'use strict' const path = require('path') const config = require('../config') // 打包css方法 const ExtractTextPlugin = require('extract-text-webpack-plugin') const packageConfig = require('../package.json') // 匹配文件夾路徑組件 https://www.cnblogs.com/waitforyou/p/7044171.html const glob = require('glob') exports.assetsPath = function (_path) { const assetsSubDirectory = process.env.NODE_ENV === 'production' ? config.build.assetsSubDirectory : config.dev.assetsSubDirectory return path.posix.join(assetsSubDirectory, _path) } exports.cssLoaders = function (options) { options = options || {} const cssLoader = { loader: 'css-loader', options: { 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) { // 判斷是否使用postcss const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader] if (loader) { loaders.push({ loader: loader + '-loader', options: Object.assign({}, loaderOptions, { sourceMap: options.sourceMap }) }) } // Extract CSS when that option is specified // (which is the case during production build) /* https://www.npmjs.com/package/extract-text-webpack-plugin 下面這一塊的配置是指,是否須要使用extract這個插件,將css總體抽取出來. 其餘倆屬性看一下api, 有一個關鍵的配置屬性. publicPath 這個屬性是指,改寫css中資源引用的路徑. -- 若是不配置這個屬性,部分例如background-image對本地文件夾圖片url的引用.抽取後會致使路徑出錯 */ if (options.extract) { return ExtractTextPlugin.extract({ use: loaders, fallback: 'vue-style-loader', publicPath: '../../../' }) } else { return ['vue-style-loader'].concat(loaders) } } // https://vue-loader.vuejs.org/en/configurations/extract-css.html return { css: generateLoaders(), postcss: generateLoaders(), less: generateLoaders('less'), sass: generateLoaders('sass', { indentedSyntax: true }), scss: generateLoaders('sass'), stylus: generateLoaders('stylus'), styl: generateLoaders('stylus') } } // Generate loaders for standalone style files (outside of .vue) 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 = () => { 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') }) } } // 多頁面模式的路徑返回方法 exports.getEntry = function (globPath) { var entries = {}, //路徑集合 basename = '', //路徑的標識 key = '', //路徑的key值 tmp; //處理數組 //能夠得到傳入path路徑下的全部文件(返回數組) glob.sync(globPath).forEach(function (item) { /* http://nodejs.cn/api/path.html path.basename(path[, ext]) 是用於返回路徑的最後部分 path.basename('/foo/bar/baz/asdf/quux.html'); // 返回: 'quux.html' path.basename('/foo/bar/baz/asdf/quux.html', '.html'); // 返回: 'quux' ------- path.extname(path) 方法返回 path 的擴展名 path.extname('index.html'); // 返回: '.html' */ basename = path.basename(item, path.extname(item)); tmp = item.split('/').splice(2); //默認進來的地址是 ./src/頁面文件夾/*** 從src後面那個開始處理 key = tmp.shift() + '/' + basename; //獲取存放頁面的文件夾名稱 (拼接成 頁面文件夾/對應頁面的格式) entries[key] = item; }) return entries; }
一些被提取了出來的配置標識項, dev.env.js標識開發環境 prod.env.js生產環境(不過其實我不知道這2個有什麼用 - -)
'use strict' // 配置項 // Template version: 1.3.1 // see http://vuejs-templates.github.io/webpack for documentation. const path = require('path') module.exports = { dev: { // 開發環境 // 靜態文件夾路徑 assetsSubDirectory: 'static', // 編譯後資源訪問的路徑 assetsPublicPath: '/', // 代理 proxyTable: { /* param: *: 表示掛代理時,識別的請求前綴 url: 表示代理的地址 例如 '/api': { target: 'http://www.baidu.com', changeOrigin: true, pathRewrite: { '^/api': '/api' } //=> localhost:8000/api => http://www.baidu.com/api } 代理的proxy格式能夠參照如下github https://github.com/chimurai/http-proxy-middleware */ }, // Various Dev Server settings // 解決了本來僅爲localhost 不能使用ip地址開發的問題 host: '0.0.0.0', // 端口 port: 8080, // 是否自動打開瀏覽器標識 autoOpenBrowser: false, // webpack-dev-server中 是否全屏彈窗的形式顯示編譯過程當中的錯誤標識 errorOverlay: true, // 配合 friendly-errors-webpack-plugin notifyOnErrors: true, // dev-server 與監視文件相關的控制選項標識 poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions- /* 這裏是關於代碼的 sourcemap 模式的選擇 可參考如下各類類型 https://segmentfault.com/a/1190000008315937 幾個類型的關鍵字 cheap eval module */ // https://webpack.js.org/configuration/devtool/#development devtool: 'cheap-module-eval-source-map', // If you have problems debugging vue-files in devtools, // set this to false - it *may* help // https://vue-loader.vuejs.org/en/options.html#cachebusting // 指的是緩存破壞,but找不到api cacheBusting: false, /* 是否開啓 CSS 的 source maps, 開啓的話將在head頭部的style中加入 source map的相關信息 */ cssSourceMap: false }, build: { //生產環境 // index模板文件 index: path.resolve(__dirname, '../dist/index.html'), // 路徑 assetsRoot: path.resolve(__dirname, '../dist'), assetsSubDirectory: 'static', // 資源引用的路徑(須要注意) assetsPublicPath: '../', /** * Source Maps */ // 是否開啓source map的標識 productionSourceMap: true, // https://webpack.js.org/configuration/devtool/#production devtool: '#source-map', // Gzip off by default as many popular static hosts such as // Surge or Netlify already gzip all static assets for you. // Before setting to `true`, make sure to: // npm install --save-dev compression-webpack-plugin // gzip壓縮 productionGzip: false, productionGzipExtensions: ['js', 'css'], // Run the build command with an extra argument to // View the bundle analyzer report after build finishes: // `npm run build --report` // Set to `true` or `false` to always turn it on or off bundleAnalyzerReport: process.env.npm_config_report } }
整理完2.0和3.0的配置內容,我發現了3.0用瞭如下一些不一樣的東西:javascript
那麼問題就來了build打包完以後,目錄結構是這樣.
css
那麼使用上面 /static這種標識在根目錄的static就會找不到資源了.因此建議使用../../的方式,或者到base.conf.js中配置alias使用.這樣去使用.
html
由於在base.conf.js中,用url-loader對圖片進行了處理:
前端
build打包完文件位置與開發不一樣,致使了css路徑就會有問題...vue
後面研究了一下build時會觸發的庫,發現是使用了extract-text-webpack-plugin將css都抽取到了一塊兒.看了一下api裏面有一個配置項publicPath.調整一下到正確的引用便可解決這個問題.
java