摘要:首先看下的代碼編譯前刪除之前編譯生成的靜態資源首先需要改的是入口文件,因為是多頁面應用,需要多個入口文件來保證打包成不同的。
一.項目簡介
? ? 本項目使用vue作為前端框架,thinkJs作為后端框架,構建個人博客網站,頁面分為博客展示和后臺管理,主要目的是學習使用thinkJs。現在只完成了主要的博客增刪改功能,發現webpack的配置遇到了一些坑,這里先記錄下。項目目錄結構如下:
其中system文件夾是前端vue項目的代碼,博客展示頁面與后臺管理頁面都在這里,打包成兩個頁面,具體webpack配置是本文重點。項目地址在這
二.搭建過程
安裝nodejs后,首先安裝thinkjs
npm install -g think-cli; thinkjs new self_blog; npm install; npm start;
這樣thinkJs項目初步搭建完成了,接下來創建vue項目。項目根目錄下新建文件夾system。
npm install -g vue-cli vue init webpack self_blog cd self_blog npm install npm run dev
這樣vue項目初步搭建完畢,接下來講下這里vue的具體webpack配置。
三.webpack配置
項目前端頁面分為博客的展示和后臺管理,這里的思路是將sytem的src下面放后臺管理頁面,在sytem下新建blog文件夾,放前臺展示頁面,打包時生成兩個html,實現webpack打包多頁面應用。目錄如下:
1.webpack.base.conf.js的配置
使用vue-cli創建項目,npm run dev運行開發環境,會使用webpack-dev-server作為前端服務器,從而實現熱加載。這樣打包的文件只會在內存里,這里我的思路是直接生成到thinkJs項目的view目錄下,通過服務端的路由返回給前端。這樣只用啟動后端的服務就行了,因為文件已經打包到服務端,前端也不存在跨域訪問后端的問題了。所以這里就不需要配置devServer了,而是改變html與js等靜態資源的生成目錄。首先看下webpack.base.conf.js的代碼:
"use strict"; const path = require("path"); const utils = require("./utils"); const config = require("../config"); const vueLoaderConfig = require("./vue-loader.conf"); const webpack = require("webpack"); const baseFileName = require("../package.json").name; const ExtractTextPlugin = require("extract-text-webpack-plugin"); const cleanWebpackPlugin = require("clean-webpack-plugin"); const AssetsPlugin = require("assets-webpack-plugin"); function resolve(dir) { return path.join(__dirname, "..", dir); } module.exports = { context: path.resolve(__dirname, "../"), entry: { app: "./src/main.js", blog: "./blog/index.js" }, output: { path: config.build.assetsRoot, 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") } }, externals: { vue: "Vue", "vue-router": "VueRouter", echarts: "echarts", ElementUI: "element-ui" }, module: { rules: [ { test: /.vue$/, loader: "vue-loader", options: vueLoaderConfig }, { 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", exclude: [resolve("src/icons")], options: { limit: 10000, name: utils.assetsPath(baseFileName + "/img/[name].[hash:7].[ext]") } }, { test: /.svg$/, loader: "svg-sprite-loader", include: [resolve("src")], options: { symbolId: "icon-[name]" } }, { test: /.(mp4|webm|ogg|mp3|wav|flac|aac)(?.*)?$/, loader: "url-loader", options: { limit: 10000, name: utils.assetsPath(baseFileName + "/media/[name].[hash:7].[ext]") } }, { test: /.(woff2?|eot|ttf|otf)(?.*)?$/, loader: "url-loader", options: { limit: 10000, name: utils.assetsPath(baseFileName + "/fonts/[name].[hash:7].[ext]") } } ] }, plugins: [ new AssetsPlugin({ filename: "build/webpack.assets.js", processOutput: function(assets) { return "window.WEBPACK_ASSETS=" + JSON.stringify(assets); } }), new webpack.optimize.CommonsChunkPlugin({ name: "vendor", minChunks: function(module) { return ( module.resource && /.js$/.test(module.resource) && module.resource.indexOf(path.join(__dirname, "../node_modules")) === 0 ); } }), new webpack.optimize.CommonsChunkPlugin({ name: "manifest", minChunks: Infinity }), new ExtractTextPlugin({ filename: utils.assetsPath( baseFileName + "/css/[name].[contenthash].css" ), allChunks: true }), // 編譯前刪除之前編譯生成的靜態資源 new cleanWebpackPlugin(["www/static/self_blog", "view/blog"], { root: resolve("../") }) ], node: { setImmediate: false, dgram: "empty", fs: "empty", net: "empty", tls: "empty", child_process: "empty" } };
首先需要改的是入口文件,因為是多頁面應用,需要多個入口文件來保證打包成不同的chunk。我們知道正常vue-cli創建的但頁面應用,會打包成三個chunk,分別是vendor.js(第三方依賴),manifest.js(異步加載的實現),app.js(業務代碼)。這里新增一個入口文件,打包時就會生成名為blog.js的chunk,含有前臺展示頁面的js業務代碼。
這里新增使用的clean-webpack-plugin,是為了每次編譯后,刪除之前生成的js,css等靜態資源,否則因為這些資源不重名,就會一直堆在你生成的目錄下。
此外一些第三方依賴,vue,elementUI什么的,我使用了cdn引入,這樣打包時這些依賴不會打進去,進而減小的vendor.js的體積。具體做法就是配置里的externals定義這些依賴,然后在生成html的模板里用script標簽直接引入cdn里的js。
注意一下,如果你開發時想用vue-devtool,需要引入vue.js,如果不用就引入vue.min.js。
2.webpack.dev.conf.js的配置
先看下代碼:
"use strict"; const utils = require("./utils"); const webpack = require("webpack"); const config = require("../config"); const merge = require("webpack-merge"); const path = require("path"); const baseWebpackConfig = require("./webpack.base.conf"); const CopyWebpackPlugin = require("copy-webpack-plugin"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const FriendlyErrorsPlugin = require("friendly-errors-webpack-plugin"); const portfinder = require("portfinder"); const HOST = process.env.HOST; const PORT = process.env.PORT && Number(process.env.PORT); const baseFileName = require("../package.json").name; function resolve(dir) { return path.join(__dirname, "..", dir); } const devWebpackConfig = merge(baseWebpackConfig, { module: { rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, extract: true, usePostCSS: true }) }, // cheap-module-eval-source-map is faster for development devtool: config.dev.devtool, output: { path: resolve(config.dev.assetsRoot), filename: "static/" + baseFileName + "/js/[name]-[hash:5].js", chunkFilename: "static/" + baseFileName + "/js/[name]-[id:5].js" }, plugins: [ new webpack.DefinePlugin({ "process.env": require("../config/dev.env") }), // new webpack.HotModuleReplacementPlugin(), new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update. new webpack.NoEmitOnErrorsPlugin(), // https://github.com/ampedandwired/html-webpack-plugin new HtmlWebpackPlugin({ filename: resolve(`../view/blog/index_index.html`), template: "./view/index.html", title: "博客管理系統", favicon: resolve("favicon.ico"), inject: true, chunks: ["manifest", "vendor", "app"] }), new HtmlWebpackPlugin({ filename: resolve(`../view/blog/blog_index.html`), template: "./view/blog.html", title: "博客展示", inject: true, chunks: ["manifest", "vendor", "blog"] }), // copy custom static assets new CopyWebpackPlugin([ { from: path.resolve(__dirname, "../static"), to: config.dev.assetsSubDirectory, ignore: [".*"] } ]) ] }); module.exports = devWebpackConfig;
這里我刪掉了之前默認配置的devSever,以及module.exports直接導出devWebpackConfig。此外,因為打包生成目錄的變化,我修改了output里面的path,filename,chunkFilename。使他們生成到self_blog根目錄的www/static下面,這也是thinkJs靜態資源的默認目錄。需要注意下,filename指的是你的出口文件(app),以及通過codespliting生成的js(vendor,manifest)的文件名;chunkFilename定義的是一些懶加載組件打包后的js文件名。
下面需要添加的就是html-webpack-plugin,因為需要打包成兩個html,所以使用兩次這個插件。除了定義生成文件名(filename),html模板(template)等,還需要定義你這個html需要的chunk,這是跟單頁面配置的一個區別。
除此之外,如果你想要開發環境打包時就分離出css,那么在使用utils.styleLoaders時,將extract置為true。因為這里的方法判斷是開發環境才使用extract-text-plugin抽離css。
3.webpack.prod.conf.js的配置
prod的配置與dev差不多,生成文件目錄也沒變,只不過多了一些js,css壓縮插件。
"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"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const ExtractTextPlugin = require("extract-text-webpack-plugin"); const OptimizeCSSPlugin = require("optimize-css-assets-webpack-plugin"); const UglifyJsPlugin = require("uglifyjs-webpack-plugin"); const baseFileName = require("../package.json").name; const env = require("../config/prod.env"); function resolve(dir) { return path.join(__dirname, "..", dir); } const webpackConfig = merge(baseWebpackConfig, { entry: { app: "./entry/entry-client-index", blog: "./entry/entry-client-blog" }, module: { rules: utils.styleLoaders({ sourceMap: config.build.productionSourceMap, extract: true, usePostCSS: true }) }, devtool: config.build.productionSourceMap ? config.build.devtool : false, output: { path: resolve(config.dev.assetsRoot), filename: "static/" + baseFileName + "/js/[name]-[chunkhash:5].js", chunkFilename: "static/" + baseFileName + "/js/[name]-[chunkhash:5].js" }, plugins: [ new webpack.DefinePlugin({ "process.env": require("../config/prod.env"), "process.env.VUE_ENV": ""client"" }), new UglifyJsPlugin({ uglifyOptions: { compress: { warnings: false } }, sourceMap: config.build.productionSourceMap, parallel: true }), new webpack.optimize.OccurrenceOrderPlugin(), new webpack.LoaderOptionsPlugin({ minimize: true }), // extract css into its own file new ExtractTextPlugin({ filename: utils.assetsPath( baseFileName + "/css/[name].[contenthash].css" ), allChunks: true }), new HtmlWebpackPlugin({ minify: {}, chunksSortMode: "dependency", environment: process.env.NODE_ENV, filename: resolve(`../view/blog/index_index.html`), template: "./view/index.html", title: "博客管理系統", favicon: resolve("favicon.ico"), inject: true, chunks: ["manifest", "vendor", "app"] }), new HtmlWebpackPlugin({ filename: resolve(`../view/blog/blog_index.html`), template: "./view/blog.html", title: "博客展示", favicon: resolve("favicon.ico"), inject: true, chunks: ["manifest", "vendor", "blog"] }), // Compress extracted CSS. We are using this plugin so that possible // duplicated CSS from different components can be deduped. new OptimizeCSSPlugin({ cssProcessorOptions: config.build.productionSourceMap ? { safe: true, map: { inline: false } } : { safe: true } }), ] }); 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 }) ); } if (config.build.bundleAnalyzerReport) { const BundleAnalyzerPlugin = require("webpack-bundle-analyzer") .BundleAnalyzerPlugin; webpackConfig.plugins.push(new BundleAnalyzerPlugin()); } module.exports = webpackConfig;
四.總結
具體可以看github上的代碼
本次項目主要目的是練習thinkJs,這里先把前期webpack配置方面的東西簡單說下,下一篇將會仔細講下thinkJs的使用方法和特性。項目會繼續更新,不少東西還沒做完呢。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/102095.html
摘要:首先看下的代碼編譯前刪除之前編譯生成的靜態資源首先需要改的是入口文件,因為是多頁面應用,需要多個入口文件來保證打包成不同的。 一.項目簡介 ? ? 本項目使用vue作為前端框架,thinkJs作為后端框架,構建個人博客網站,頁面分為博客展示和后臺管理,主要目的是學習使用thinkJs。現在只完成了主要的博客增刪改功能,發現webpack的配置遇到了一些坑,這里先記錄下。項目目錄結構如下...
摘要:插件機制可以說是自定義的鉤子函數。首先在新建文件夾,新建文件以為例更新內容緩存里對應的數組表示鉤子函數的調用名,具體調用的是下面的方法。 一.簡介 這個個人博客網站最初制作的目的就是練習使用thinkJs,這一篇就主要講一下thinkJs的一些特性和注意事項。涉及到了文件上傳,thinkJs的插件機制,model層建立以及CURD的編寫方式等。本項目github地址在這里。 項目thi...
摘要:插件機制可以說是自定義的鉤子函數。首先在新建文件夾,新建文件以為例更新內容緩存里對應的數組表示鉤子函數的調用名,具體調用的是下面的方法。 一.簡介 這個個人博客網站最初制作的目的就是練習使用thinkJs,這一篇就主要講一下thinkJs的一些特性和注意事項。涉及到了文件上傳,thinkJs的插件機制,model層建立以及CURD的編寫方式等。本項目github地址在這里。 項目thi...
摘要:插件機制可以說是自定義的鉤子函數。首先在新建文件夾,新建文件以為例更新內容緩存里對應的數組表示鉤子函數的調用名,具體調用的是下面的方法。 一.簡介 這個個人博客網站最初制作的目的就是練習使用thinkJs,這一篇就主要講一下thinkJs的一些特性和注意事項。涉及到了文件上傳,thinkJs的插件機制,model層建立以及CURD的編寫方式等。本項目github地址在這里。 項目thi...
摘要:一入冬懶癌發作,給自己找點事干。之前博客程序寫過幾次,的寫過兩次,用寫過,隨著版本從升級到之前的博客程序也做過升級。這里主要記錄一下開發過程中遇到的問題和解決方法。后端使用守護進程即可。 一入冬懶癌發作,給自己找點事干。之前博客程序寫過幾次,php 的寫過兩次,nodejs 用 ThinkJS 寫過,隨著 ThinkJS 版本從1.x 升級到 2.x 之前的博客程序也做過升級。但是因為...
閱讀 1231·2021-11-11 16:54
閱讀 881·2021-10-19 11:44
閱讀 1344·2021-09-22 15:18
閱讀 2453·2019-08-29 16:26
閱讀 2956·2019-08-29 13:57
閱讀 3099·2019-08-26 13:32
閱讀 1087·2019-08-26 11:58
閱讀 2336·2019-08-26 10:37