摘要:本文記錄了用搭建項目后,配置成多頁面應用的過程。項目地址首先全局安裝創建初始項目創建后默認是一個單頁面應用,在默認結構的基礎上將目錄結構改為如下形式。其中目錄下的和就是多頁面應用中的兩個頁面。
vue-multi-pages 本文記錄了用@vue/cli+webpack搭建項目后,配置成多頁面應用的過程。
項目地址:https://github.com/mandyshen9...
首先全局安裝@vue/cli
npm install -g @vue/cli
創建@vue/cli+webpack初始項目
vue init webpack my-project
創建后默認是一個vue單頁面應用,在默認結構的基礎上將目錄結構改為如下形式。其中pages目錄下的cell和home就是多頁面應用中的兩個頁面。
下面修改配置 build目錄下的utils.js文件"use strict" const path = require("path") const config = require("../config") const ExtractTextPlugin = require("extract-text-webpack-plugin") const packageConfig = require("../package.json") 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) { 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) if (options.extract) { return ExtractTextPlugin.extract({ use: loaders, fallback: "vue-style-loader" }) } 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 } /*這里是多頁面添加的部分------------------------------------開始*/ // glob是webpack安裝時依賴的一個第三方模塊,該模塊允許你使用 *等符號, 例如lib/*.js就是獲取lib文件夾下的所有js后綴名的文件 var glob = require("glob") // 頁面模板 var HtmlWebpackPlugin = require("html-webpack-plugin") // 取得相應的頁面路徑,因為之前的配置,所以在本項目中是src文件夾下的pages文件夾 var PAGE_PATH = path.resolve(__dirname, "../src/pages") // 用于做相應的merge處理 var merge = require("webpack-merge") //多入口配置 // 通過glob模塊讀取pages文件夾下的所有對應文件夾下的js后綴文件,如果該文件存在 // 那么就作為入口處理 exports.entries = function () { var entryFiles = glob.sync(PAGE_PATH + "/*/*.js") var map = {} entryFiles.forEach((filePath) => { var filename = filePath.substring(filePath.lastIndexOf("/") + 1, filePath.lastIndexOf(".")) map[filename] = filePath }) return map } //多頁面輸出配置 // 與上面的多頁面入口配置相同,讀取pages文件夾下的對應的html后綴文件,然后放入數組中 exports.htmlPlugin = function () { let entryHtml = glob.sync(PAGE_PATH + "/*/*.html") let arr = [] entryHtml.forEach((filePath) => { let filename = filePath.substring(filePath.lastIndexOf("/") + 1, filePath.lastIndexOf(".")) let conf = { // 模板來源 template: filePath, // 文件名稱 filename: filename + ".html", // 頁面模板需要加對應的js腳本,如果不加這行則每個頁面都會引入所有的js腳本 chunks: ["manifest", "vendor", filename], inject: true } if (process.env.NODE_ENV === "production") { conf = merge(conf, { minify: { removeComments: true, collapseWhitespace: true, removeAttributeQuotes: true }, chunksSortMode: "dependency" }) } arr.push(new HtmlWebpackPlugin(conf)) }) return arr } /* 這里是添加的部分--------------------------------------------結束*/ 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") }) } }build目錄下的webpack.base.conf.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) } const createLintingRule = () => ({ test: /.(js|vue)$/, loader: "eslint-loader", enforce: "pre", include: [resolve("src"), resolve("test")], options: { formatter: require("eslint-friendly-formatter"), emitWarning: !config.dev.showEslintErrorsInOverlay } }) module.exports = { context: path.resolve(__dirname, "../"), /*多頁面入口修改-------------------------------開始 */ // 將原來默認的入口配置注釋掉 // entry: { // app: "./src/main.js" // }, // 添加多頁面入口配置 entry: utils.entries(), /*多頁面入口修改-------------------------------結束 */ 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"), } }, module: { rules: [ ...(config.dev.useEslint ? [createLintingRule()] : []), { 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", options: { limit: 10000, 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" } }
build目錄下的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 devWebpackConfig = merge(baseWebpackConfig, { module: { rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true }) }, // cheap-module-eval-source-map is faster for development devtool: config.dev.devtool, // these devServer options should be customized in /config/index.js devServer: { clientLogLevel: "warning", historyApiFallback: { rewrites: [ { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, "index.html") }, ], }, hot: true, contentBase: false, // since we use CopyWebpackPlugin. compress: true, host: HOST || config.dev.host, port: PORT || config.dev.port, open: config.dev.autoOpenBrowser, overlay: config.dev.errorOverlay ? { warnings: false, errors: true } : false, publicPath: config.dev.assetsPublicPath, proxy: config.dev.proxyTable, quiet: true, // necessary for FriendlyErrorsPlugin watchOptions: { poll: config.dev.poll, } }, 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: "index.html", // template: "index.html", // inject: true // }), /*注釋這個區域的代碼------------------------------------------結束 */ // copy custom static assets new CopyWebpackPlugin([ { from: path.resolve(__dirname, "../static"), to: config.dev.assetsSubDirectory, ignore: [".*"] } ]) /*添加 .concat(utils.htmlPlugin())-----------------------------開始 */ ].concat(utils.htmlPlugin()) /*添加 .concat(utils.htmlPlugin())-------------------------------結束*/ }) 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 // Add FriendlyErrorsPlugin 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) } }) })build目錄下的webpack.prod.conf.js文件
"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 CopyWebpackPlugin = require("copy-webpack-plugin") 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 env = process.env.NODE_ENV === "testing" ? require("../config/test.env") : require("../config/prod.env") const webpackConfig = merge(baseWebpackConfig, { module: { rules: utils.styleLoaders({ sourceMap: config.build.productionSourceMap, extract: true, usePostCSS: true }) }, devtool: config.build.productionSourceMap ? config.build.devtool : false, 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 }), new UglifyJsPlugin({ uglifyOptions: { compress: { warnings: false } }, sourceMap: config.build.productionSourceMap, parallel: true }), // extract css into its own file 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. 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 /*注釋這個區域的內容------------------------------------------------------------------開始 */ // new HtmlWebpackPlugin({ // filename: process.env.NODE_ENV === "testing" // ? "index.html" // : config.build.index, // template: "index.html", // inject: true, // minify: { // removeComments: true, // collapseWhitespace: true, // removeAttributeQuotes: true // // more options: // // https://github.com/kangax/html-minifier#options-quick-reference // }, // // necessary to consistently work with multiple chunks via CommonsChunkPlugin // chunksSortMode: "dependency" // }), /*注釋這個區域的內容--------------------------------------------------------------------結束 */ // keep module.id stable when vendor modules does not change new webpack.HashedModuleIdsPlugin(), // enable scope hoisting new webpack.optimize.ModuleConcatenationPlugin(), // split vendor js into its own file new webpack.optimize.CommonsChunkPlugin({ name: "vendor", minChunks (module) { // any required modules inside node_modules are extracted to vendor return ( module.resource && /.js$/.test(module.resource) && module.resource.indexOf( path.join(__dirname, "../node_modules") ) === 0 ) } }), // extract webpack runtime and module manifest to its own file in order to // prevent vendor hash from being updated whenever app bundle is updated 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 }), // copy custom static assets new CopyWebpackPlugin([ { from: path.resolve(__dirname, "../static"), to: config.build.assetsSubDirectory, ignore: [".*"] } ]) /*該位置添加.concat(utils.htmlPlugin())-------------------------------------------開始 */ ].concat(utils.htmlPlugin()) /*該位置添加.concat(utils.htmlPlugin())-------------------------------------------結束 */ }) 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寫頁面
在cell 和 home 頁面目錄下分別創建js和html文件。具體代碼見項目目錄代碼https://github.com/mandyshen9...。
運行項目
npm start
效果:
home頁面(頁面1):
cell頁面(頁面2):
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/106138.html
摘要:五六月份推薦集合查看最新的請點擊集前端最近很火的框架資源定時更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥雀呼晴,侵曉窺檐語。葉上初陽乾宿雨,水面清圓,一一風荷舉。家住吳門,久作長安旅。五月漁郎相憶否。小楫輕舟,夢入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請::點擊::集web前端最近很火的vue2框架資源;定時更新,歡迎 Star 一下。 蘇...
摘要:五六月份推薦集合查看最新的請點擊集前端最近很火的框架資源定時更新,歡迎一下。蘇幕遮燎沈香宋周邦彥燎沈香,消溽暑。鳥雀呼晴,侵曉窺檐語。葉上初陽乾宿雨,水面清圓,一一風荷舉。家住吳門,久作長安旅。五月漁郎相憶否。小楫輕舟,夢入芙蓉浦。 五、六月份推薦集合 查看github最新的Vue weekly;請::點擊::集web前端最近很火的vue2框架資源;定時更新,歡迎 Star 一下。 蘇...
摘要:如何在下搭建多模塊單模塊多路由骨架屏前言骨架屏的用戶感知比更好,此前看過很多專欄以及文章,此次實踐中還是遇到需要學習的部分。包括因為可能信息面不全,對插件源碼進行了詳細解讀,希望對于將要在項目中搭建骨架屏的小伙伴們有所幫助。 如何在webpack+vue+vue-cli下搭建多模塊/單模塊多路由骨架屏 前言 骨架屏的用戶感知比loading更好,此前看過很多專欄以及文章,此次實踐中還是...
摘要:如何在下搭建多模塊單模塊多路由骨架屏前言骨架屏的用戶感知比更好,此前看過很多專欄以及文章,此次實踐中還是遇到需要學習的部分。包括因為可能信息面不全,對插件源碼進行了詳細解讀,希望對于將要在項目中搭建骨架屏的小伙伴們有所幫助。 如何在webpack+vue+vue-cli下搭建多模塊/單模塊多路由骨架屏 前言 骨架屏的用戶感知比loading更好,此前看過很多專欄以及文章,此次實踐中還是...
閱讀 1047·2021-09-13 10:29
閱讀 3395·2019-08-29 18:31
閱讀 2638·2019-08-29 11:15
閱讀 3017·2019-08-26 13:25
閱讀 1376·2019-08-26 12:00
閱讀 2307·2019-08-26 11:41
閱讀 3404·2019-08-26 10:31
閱讀 1493·2019-08-26 10:25