vue 多页面应用例子_vue+vuecli+webapck2实现多页面应用

本文介绍了如何使用Vue CLI创建一个多页面应用。通过修改webpack配置,包括utils.js、webpack.base.conf.js、webpack.dev.conf.js和webpack.prod.conf.js,实现了根据src/pages目录下的子目录自动配置多个入口和HTML页面生成。在开发环境和生产环境中,利用HtmlWebpackPlugin处理HTML文件,实现不同页面的跳转和资源加载。最后,文章提到了页面跳转时需要注意的路径问题。
摘要由CSDN通过智能技术生成

准备工作

在本地用vue-cli新建一个项目,首先安装vue-cil,命令:

npm install -g vue-cli

新建一个vue项目,创建一个基于"webpack"的项目,项目名为vuedemo:

vue init webpack vuedemo

这里有一个地方需要改一下,在执行npm install命令之前,在package.json里添加一个依赖,后面会用到。

修改webpack配置

项目目录

├── README.md

├── build

│ ├── build.js

│ ├── check-versions.js

│ ├── dev-client.js

│ ├── dev-server.js

│ ├── utils.js

│ ├── vue-loader.conf.js

│ ├── webpack.base.conf.js

│ ├── webpack.dev.conf.js

│ └── webpack.prod.conf.js

├── config

│ ├── dev.env.js

│ ├── index.js

│ └── prod.env.js

├── package.json

├── src

│ ├── assets

│ │ └── logo.png

│ ├── components

│ │ ├── Hello.vue

│ │ └── cell.vue

│ └── pages

│ ├── cell

│ │ ├── cell.html

│ │ ├── cell.js

│ │ └── cell.vue

│ └── index

│ ├── index.html

│ ├── index.js

│ ├── index.vue

│ └── router

│ └── index.js

└── static

在这一步里我们需要改动的文件都在build文件下,分别是:

utils.js

webpack.base.conf.js

webpack.dev.conf.js

webpack.prod.conf.js

utils.js文件

//utils.js文件

var path = require('path')var config = require('../config')var ExtractTextPlugin = require('extract-text-webpack-plugin')

exports.assetsPath= function(_path) {var assetsSubDirectory = process.env.NODE_ENV === 'production' ?config.build.assetsSubDirectory :

config.dev.assetsSubDirectoryreturnpath.posix.join(assetsSubDirectory, _path)

}

exports.cssLoaders= function(options) {

options= options ||{}var cssLoader ={

loader:'css-loader',

options: {

minimize: process.env.NODE_ENV=== 'production',

sourceMap: options.sourceMap

}

}//generate loader string to be used with extract text plugin

functiongenerateLoaders(loader, loaderOptions) {var loaders =[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) {returnExtractTextPlugin.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) {var output =[]var loaders =exports.cssLoaders(options)for (var extension inloaders) {var loader =loaders[extension]

output.push({

test:new RegExp('\\.' + extension + '$'),

use: loader

})

}returnoutput

}/*这里是添加的部分 ---------------------------- 开始*/

//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

})returnmap

}//多页面输出配置//与上面的多页面入口配置相同,读取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(newHtmlWebpackPlugin(conf))

})returnarr

}/*这里是添加的部分 ---------------------------- 结束*/

webpack.base.conf.js 文件

//webpack.base.conf.js 文件

var path = require('path')var utils = require('./utils')var config = require('../config')var vueLoaderConfig = require('./vue-loader.conf')functionresolve(dir) {return path.join(__dirname, '..', dir)

}

module.exports={/*修改部分 ---------------- 开始*/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'),'pages': resolve('src/pages'),'components': resolve('src/components')

}

},

module: {

rules: [{

test:/\.vue$/,

loader:'vue-loader',

options: vueLoaderConfig

},

{

test:/\.js$/,

loader:'babel-loader',

include: [resolve('src'), resolve('test')]

},

{

test:/\.(png|jpe?g|gif|svg)(\?.*)?$/,

loader:'url-loader',

options: {

limit:10000,

name: utils.assetsPath('img/[name].[hash:7].[ext]')

}

},

{

test:/\.(woff2?|eot|ttf|otf)(\?.*)?$/,

loader:'url-loader',

options: {

limit:10000,

name: utils.assetsPath('fonts/[name].[hash:7].[ext]')

}

}

]

}

}

webpack.dev.conf.js 文件

var utils = require('./utils')var webpack = require('webpack')var config = require('../config')var merge = require('webpack-merge')var baseWebpackConfig = require('./webpack.base.conf')var HtmlWebpackPlugin = require('html-webpack-plugin')var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')//add hot-reload related code to entry chunks

Object.keys(baseWebpackConfig.entry).forEach(function(name) {

baseWebpackConfig.entry[name]= ['./build/dev-client'].concat(baseWebpackConfig.entry[name])

})

module.exports=merge(baseWebpackConfig, {

module: {

rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap })

},//cheap-module-eval-source-map is faster for development

devtool: '#cheap-module-eval-source-map',

plugins: [newwebpack.DefinePlugin({'process.env': config.dev.env

}),//https://github.com/glenjamin/webpack-hot-middleware#installation--usage

newwebpack.HotModuleReplacementPlugin(),newwebpack.NoEmitOnErrorsPlugin(),//https://github.com/ampedandwired/html-webpack-plugin

/*注释这个区域的文件 ------------- 开始*/

//new HtmlWebpackPlugin({

//filename: 'index.html',

//template: 'index.html',

//inject: true

//}),

/*注释这个区域的文件 ------------- 结束*/

newFriendlyErrorsPlugin()/*添加 .concat(utils.htmlPlugin()) ------------------*/].concat(utils.htmlPlugin())

})

webpack.prod.conf.js 文件

var path = require('path')var utils = require('./utils')var webpack = require('webpack')var config = require('../config')var merge = require('webpack-merge')var baseWebpackConfig = require('./webpack.base.conf')var CopyWebpackPlugin = require('copy-webpack-plugin')var HtmlWebpackPlugin = require('html-webpack-plugin')var ExtractTextPlugin = require('extract-text-webpack-plugin')var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')var env =config.build.envvar webpackConfig =merge(baseWebpackConfig, {

module: {

rules: utils.styleLoaders({

sourceMap: config.build.productionSourceMap,

extract:true})

},

devtool: config.build.productionSourceMap? '#source-map' : 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

newwebpack.DefinePlugin({'process.env': env

}),newwebpack.optimize.UglifyJsPlugin({

compress: {

warnings:false},

sourceMap:true}),//extract css into its own file

newExtractTextPlugin({

filename: utils.assetsPath('css/[name].[contenthash].css')

}),//Compress extracted CSS. We are using this plugin so that possible

//duplicated CSS from different components can be deduped.

newOptimizeCSSPlugin({

cssProcessorOptions: {

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: 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'

//}),

/*注释这个区域的内容 ---------------------- 结束*/

//split vendor js into its own file

newwebpack.optimize.CommonsChunkPlugin({

name:'vendor',

minChunks:function(module, count) {//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

newwebpack.optimize.CommonsChunkPlugin({

name:'manifest',

chunks: ['vendor']

}),//copy custom static assets

newCopyWebpackPlugin([{

from: path.resolve(__dirname,'../static'),

to: config.build.assetsSubDirectory,

ignore: ['.*']

}])/*该位置添加 .concat(utils.htmlPlugin()) -------------------*/].concat(utils.htmlPlugin())

})if(config.build.productionGzip) {var CompressionWebpackPlugin = require('compression-webpack-plugin')

webpackConfig.plugins.push(newCompressionWebpackPlugin({

asset:'[path].gz[query]',

algorithm:'gzip',

test:newRegExp('\\.(' +config.build.productionGzipExtensions.join('|') +

')$'),

threshold:10240,

minRatio:0.8})

)

}if(config.build.bundleAnalyzerReport) {var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin

webpackConfig.plugins.push(newBundleAnalyzerPlugin())

}

module.exports= webpackConfig

至此,webpack的配置就结束了。

文件结构

├── src

│ ├── assets

│ │ └── logo.png

│ ├── components

│ │ ├── Hello.vue

│ │ └── cell.vue

│ └── pages

│ ├── cell

│ │ ├── cell.html

│ │ ├── cell.js

│ │ └── cell.vue

│ └── index

│ ├── index.html

│ ├── index.js

│ ├── index.vue

│ └── router

│ └── index.js

src就是我所使用的工程文件了,assets,components,pages分别是静态资源文件、组件文件、页面文件。

原先,入口文件只有一个main.js,但现在由于是多页面,因此入口页面多了,我目前就是两个:index和cell,之后如果打包,就会在dist文件下生成两个HTML文件:index.html和cell.html(可以参考一下单页面应用时,打包只会生成一个index.html,区别在这里)。

页面跳转问题

既然是多页面,肯定涉及页面之间的互相跳转,就按照我这个项目举例,从index.html文件点击a标签跳转到cell.html。

一般都认为这样写:

但这样写,不论是在开发环境还是最后测试,都会报404,找不到这个页面。

改成这样既可:

如果想跳转到另外一个路由配置的某个模块,如账号中心,如下例子:

{{userInfo.phone}}

参考地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值