摘要:前言弄完了前后端分離,我們自然想打包發布項目了。下篇我們會來完成測試的流程從零開始做前端架構項目完整代碼前端架構子咻
前言
弄完了前后端分離,我們自然想打包發布項目了。
不多說,就讓我們來看看吧。
直接上代碼:
const webpack = require("webpack") const path = require("path") const ExtractTextPlugin = require("extract-text-webpack-plugin") const webpackConfigBase = require("./webpack.config.js") const HtmlWebpackPlugin = require("html-webpack-plugin") const CleanWebpackPlugin = require("clean-webpack-plugin") const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin const exec = require("child_process").execSync const pkg = require("./package.json") // 為了抽離出兩份CSS,創建兩份ExtractTextPlugin // base作為基礎的css,基本不變,所以,可以抽離出來充分利用瀏覽器緩存 // app作為迭代的css,會經常改變 const extractBaseCSS = new ExtractTextPlugin({filename:"static/css/base.[chunkhash:8].css", allChunks: true}) const extractAppCSS = new ExtractTextPlugin({filename:"static/css/app.[chunkhash:8].css", allChunks: true}) // 減少路徑書寫 function resolve(dir) { return path.join(__dirname, dir) } // 網站圖標配置 const favicon = resolve("favicon.ico") // 網站版本號設置 let appVersion = "" try { appVersion = exec("git rev-parse --short HEAD").toString().replace(/ /, "") } catch (e) { console.warn("Getting revision FAILED. Maybe this is not a git project.") } const config = Object.assign(webpackConfigBase, { // You should configure your server to disallow access to the Source Map file for normal users! devtool: "source-map", entry: { app: resolve("app/index.js"), // 將第三方依賴(node_modules)的庫打包,從而充分利用瀏覽器緩存 vendor: Object.keys(pkg.dependencies) }, output: { path: resolve("dist"), // publicPath: "https://cdn.self.com" publicPath: resolve("dist/"), filename: "static/js/[name].[chunkhash:8].js" }, module: { rules: [ { test: /.js$/, include: [resolve("app")], loader: "babel-loader" }, { test: /.vue$/, exclude: /node_modules/, loader: "vue-loader", options: { extractCSS: true, loaders: { scss: extractAppCSS.extract({ fallback: "vue-style-loader", use: [ { loader: "css-loader", options: { sourceMap: true } }, { loader: "postcss-loader", options: { sourceMap: true } }, { loader: "sass-loader", options: { sourceMap: true } } ] }) } } }, { test: /.(css|scss)$/, use: extractBaseCSS.extract({ fallback: "style-loader", use: [ { loader: "css-loader", options: { sourceMap: true } }, { loader: "postcss-loader", options: { sourceMap: true } }, { loader: "sass-loader", options: { sourceMap: true } } ] }) }, { test: /.(png|jpe?g|gif|svg|ico)(?.*)?$/, loader: "url-loader", options: { limit: 8192, name: "static/img/[name].[hash:8].[ext]" } }, { test: /.(woff2?|eot|ttf|otf)(?.*)?$/, loader: "url-loader", options: { limit: 8192, name: "static/font/[name].[hash:8].[ext]" } } ] }, plugins: [ // Scope hosting new webpack.optimize.ModuleConcatenationPlugin(), // 刪除build文件夾 new CleanWebpackPlugin( resolve("dist") ), // 抽離出css extractBaseCSS, extractAppCSS, // 提供公共代碼vendor new webpack.optimize.CommonsChunkPlugin({ name: "vendor", filename: "static/js/[name].[chunkhash:8].js" }), // html 模板插件 new HtmlWebpackPlugin({ appVersion, favicon, filename: "index.html", template: resolve("app/index.html"), minify: { removeComments: true, collapseWhitespace: false } }), // 定義全局常量 new webpack.DefinePlugin({ "process.env": { NODE_ENV: ""production"" } }), // 可視化分析 new BundleAnalyzerPlugin(), // 加署名 new webpack.BannerPlugin("Copyright by 子咻 https://github.com/CodeLittlePrince/blog"), ] }) module.exports = config
代碼幾乎全都有注釋,有不懂的可以在評論去留言。
思考雖然代碼寫好了,但是我們不禁發出一聲“臥槽”,好多和webpack.config.js一樣的代碼啊,要是改了一樣的代碼部分,我還得同時改兩份,而且,這么多的冗余代碼對于一個優秀的程序員來講,是不可容忍的。
那我們改怎么呢?
我們就叫webapck.config.base.js吧:
const path = require("path") // 為了抽離出兩份CSS,創建兩份ExtractTextPlugin // base作為基礎的css,基本不變,所以,可以抽離出來充分利用瀏覽器緩存 // app作為迭代的css,會經常改變 const isProduction = process.env.NODE_ENV === "production" const ExtractTextPlugin = require("extract-text-webpack-plugin") const extractBaseCSS = new ExtractTextPlugin( { filename:"static/css/base.[chunkhash:8].css", allChunks: true, disable: !isProduction // 開發環境下不抽離css } ) const extractAppCSS = new ExtractTextPlugin( { filename:"static/css/app.[chunkhash:8].css", allChunks: true, disable: !isProduction // 開發環境下不抽離css } ) // 減少路徑書寫 function resolve(dir) { return path.join(__dirname, dir) } // 網站圖標配置 const favicon = resolve("favicon.ico") // __dirname: 總是返回被執行的 js 所在文件夾的絕對路徑 // __filename: 總是返回被執行的 js 的絕對路徑 // process.cwd(): 總是返回運行 node 命令時所在的文件夾的絕對路徑 const config = { resolve: { // 擴展名,比如import "app.vue",擴展后只需要寫成import "app"就可以了 extensions: [".js", ".vue", ".scss", ".css"], // 取路徑別名,方便在業務代碼中import alias: { api: resolve("app/api/"), common: resolve("app/common/"), views: resolve("app/views/"), components: resolve("app/components/"), componentsBase: resolve("app/componentsBase/"), directives: resolve("app/directives/"), filters: resolve("app/filters/"), mixins: resolve("app/mixins/") } }, // loaders處理 module: { rules: [ { test: /.js$/, include: [resolve("app")], loader: [ "babel-loader", "eslint-loader" ] }, { test: /.vue$/, exclude: /node_modules/, loader: "vue-loader", options: { extractCSS: true, loaders: { scss: extractAppCSS.extract({ fallback: "vue-style-loader", use: [ { loader: "css-loader", options: { sourceMap: true } }, { loader: "postcss-loader", options: { sourceMap: true } }, { loader: "sass-loader", options: { sourceMap: true } } ] }) } } }, { test: /.(css|scss)$/, use: extractBaseCSS.extract({ fallback: "style-loader", use: [ { loader: "css-loader", options: { sourceMap: true } }, { loader: "postcss-loader", options: { sourceMap: true } }, { loader: "sass-loader", options: { sourceMap: true } } ] }) }, { test: /.(png|jpe?g|gif|svg|ico)(?.*)?$/, loader: "url-loader", options: { limit: 8192, name: isProduction ? "static/img/[name].[hash:8].[ext]" : "static/img/[name].[ext]" } }, { test: /.(woff2?|eot|ttf|otf)(?.*)?$/, loader: "url-loader", options: { limit: 8192, name: isProduction ? "static/font/[name].[hash:8].[ext]" : "static/font/[name].[ext]" } } ] } } module.exports = { config, favicon, resolve, extractBaseCSS, extractAppCSS }二、重構webpack開發環境配置
const webpack = require("webpack") const HtmlWebpackPlugin = require("html-webpack-plugin") const FriendlyErrorsPlugin = require("friendly-errors-webpack-plugin") const webpackConfigBase = require("./webpack.config.base.js") const config = Object.assign(webpackConfigBase.config, { // sourcemap 模式 devtool: "cheap-module-eval-source-map", // 入口 entry: { app: [ "babel-polyfill", // 這里是配合babel-present-env導入的動態babel-polyfill,因此npm需dev依賴 webpackConfigBase.resolve("app/index.js") ] }, // 輸出 output: { path: webpackConfigBase.resolve("dev"), filename: "index.bundle.js" }, plugins: [ // html 模板插件 new HtmlWebpackPlugin({ favicon: webpackConfigBase.favicon, filename: "index.html", template: webpackConfigBase.resolve("app/index.html") }), // 抽離出css,開發環境其實不抽離,但是為了配合extract-text-webpack-plugin插件,需要做個樣子 webpackConfigBase.extractAppCSS, webpackConfigBase.extractBaseCSS, // 熱替換插件 new webpack.HotModuleReplacementPlugin(), // 更友好地輸出錯誤信息 new FriendlyErrorsPlugin() ], devServer: { proxy: { // 凡是 `/api` 開頭的 http 請求,都會被代理到 localhost:7777 上,由 koa 提供 mock 數據。 // koa 代碼在 ./mock 目錄中,啟動命令為 npm run mock。 "/api": { target: "http://localhost:7777", // 如果說聯調了,將地址換成后端環境的地址就哦了 secure: false } }, host: "0.0.0.0", port: "9999", disableHostCheck: true, // 為了手機可以訪問 contentBase: webpackConfigBase.resolve("dev"), // 本地服務器所加載的頁面所在的目錄 // historyApiFallback: true, // 為了SPA應用服務 inline: true, //實時刷新 hot: true // 使用熱加載插件 HotModuleReplacementPlugin } }) module.exports = config三、重構webpack開發環境配置
const webpack = require("webpack") const HtmlWebpackPlugin = require("html-webpack-plugin") const CleanWebpackPlugin = require("clean-webpack-plugin") const BundleAnalyzerPlugin = require("webpack-bundle-analyzer").BundleAnalyzerPlugin const exec = require("child_process").execSync const webpackConfigBase = require("./webpack.config.base.js") const pkg = require("./package.json") // 網站版本號設置 let appVersion = "" try { appVersion = exec("git rev-parse --short HEAD").toString().replace(/ /, "") } catch (e) { console.warn("Getting revision FAILED. Maybe this is not a git project.") } const config = Object.assign(webpackConfigBase.config, { // You should configure your server to disallow access to the Source Map file for normal users! devtool: "source-map", entry: { app: webpackConfigBase.resolve("app/index.js"), // 將第三方依賴(node_modules)的庫打包,從而充分利用瀏覽器緩存 vendor: Object.keys(pkg.dependencies) }, output: { path: webpackConfigBase.resolve("dist"), // publicPath: "https://cdn.self.com" publicPath: webpackConfigBase.resolve("dist/"), filename: "static/js/[name].[chunkhash:8].js" }, plugins: [ // Scope hosting new webpack.optimize.ModuleConcatenationPlugin(), // 刪除build文件夾 new CleanWebpackPlugin( webpackConfigBase.resolve("dist") ), // 抽離出css webpackConfigBase.extractAppCSS, webpackConfigBase.extractBaseCSS, // 提取公共代碼vendor new webpack.optimize.CommonsChunkPlugin({ name: "vendor", filename: "static/js/[name].[chunkhash:8].js" }), // html 模板插件 new HtmlWebpackPlugin({ appVersion, favicon: webpackConfigBase.favicon, filename: "index.html", template: webpackConfigBase.resolve("app/index.html"), minify: { removeComments: true, collapseWhitespace: false } }), // 定義全局常量 new webpack.DefinePlugin({ "process.env": { NODE_ENV: ""production"" } }), // 可視化分析 new BundleAnalyzerPlugin(), // 加署名 new webpack.BannerPlugin("Copyright by 子咻 https://github.com/CodeLittlePrince/blog"), ] }) module.exports = config
代碼瞬間變得清晰、精簡、高大上有沒有?!(^-^)V
看一下打包處理后代碼情況(兼容IE10及以上):
總結這一篇我們編寫了開發環境用的webpack配置文件,然后發現代碼的冗余從而重構了開發和發布環境的webpack配置。
之后,我們還需要能夠自動測試我們寫的業務代碼,避免人工手動各種戳頁面(雖然大部分公司都是這么干的,即使是大公司會騰出時間和人手寫測試用例的部門也不多),不過架構還是要做的。
下篇我們會來完成測試的流程 - 從零開始做Vue前端架構(6)
項目完整代碼Vue前端架構-by 子咻
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/11836.html
摘要:前言上一篇我們遇到少年,是不是忘了的警告,這一篇我們就來解決這個問題。總結通過實現前后端分離,并且使用來更方便的模擬數據。下一篇,我們創建發布環境下的配置文件,并且看看怎么優化產出的代碼的從零開始做前端架構項目完整代碼前端架構子咻 前言 上一篇我們遇到少年,是不是忘了npm run mock?的警告,這一篇我們就來解決這個問題。 開發 一、安裝包 安裝koa和一系列的包(我們用的是ko...
摘要:前言這一篇,我們將接著上篇來完成創建項目文件目錄架構。總結這篇主要是文件和目錄架構的東西,讀者務必運行一下完整的項目。因此,下一篇,我們將通過實現本地數據接口模擬從零開始做前端架構項目完整代碼前端架構子咻 前言 這一篇,我們將接著上篇來完成創建項目文件、目錄架構。 回顧 先回顧一下現在項目有哪些東西了: . ├── app │?? ├── app.vue │?? ├── common ...
摘要:前言想想也已經做過不少架構的項目了,有基于,基于,基于,基于的。好了,介紹完畢,接下來,我就從零開始,一步一步建起前后端完全分離的前端架構了。 前言 想想也已經做過不少架構的項目了,有基于vue,基于react,基于thinkPHP,基于laravel的。 做多了,也就對現有的架構有各種想法,有好的,有壞的,總之,用起來還是不爽。vue-cli雖然可以很快地構建并使用,尤其是vue-c...
摘要:前言這一篇,我們將接著上篇來完成配置。開發一配置我們采用的方式來創建。對了,前提我們需要全局安裝。三配置創建文件,上配置配置總結這篇不多,就做了三件事,。下一篇我們將創建項目文件目錄架構從零開始做前端架構項目完整代碼前端架構子咻 前言 這一篇,我們將接著上篇來完成配置eslint、babel、postcss。 開發 一、配置eslint 我們采用eslint --init的方式來創建e...
摘要:前言這一篇,我們將接著上篇來完成配置。開發一配置我們采用的方式來創建。對了,前提我們需要全局安裝。三配置創建文件,上配置配置總結這篇不多,就做了三件事,。下一篇我們將創建項目文件目錄架構從零開始做前端架構項目完整代碼前端架構子咻 前言 這一篇,我們將接著上篇來完成配置eslint、babel、postcss。 開發 一、配置eslint 我們采用eslint --init的方式來創建e...
摘要:那該怎么管理這兩個不同的項目呢解決子模塊用的的同學肯定一下子就想到子模塊的知識了。最后,也希望有想法的同學還有大佬多多留言,給點建議原文地址從零開始做前端架構腳手架參考資料官方文檔使用定制前端腳手架別人寫的腳手架文件操作相關文檔子模塊 前言 相信很多人都用過vue-cli或create-react-app或者類似的腳手架。腳手架方便我們復制,粘貼,或者clone代碼庫,而且還可以更具用...
閱讀 2513·2023-04-25 17:27
閱讀 1824·2019-08-30 15:54
閱讀 2369·2019-08-30 13:06
閱讀 2980·2019-08-30 11:04
閱讀 746·2019-08-29 15:30
閱讀 729·2019-08-29 15:16
閱讀 1733·2019-08-26 10:10
閱讀 3603·2019-08-23 17:02