准备工作
在本地用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}}
参考地址