准备工作
在本地用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
- 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.assetsSubDirectory return path.posix.join(assetsSubDirectory,_path) } exports.cssLoaders = (options) { options = options || {} var cssLoader = { loader: 'css-loader',options: { minimize: process.env.NODE_ENV === 'production' generate loader string to be used with extract text plugin generateLoaders(loader,loaderOptions) { var loaders = [cssLoader] if (loader) { loaders.push({ loader: loader + '-loader' Extract CSS when that option is specified (which is the case during production build) (options.extract) { 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 { css: generateLoaders(),postcss: generateLoaders(),less: generateLoaders('less'),sass: generateLoaders('sass',{ indentedSyntax: true }),scss: generateLoaders('sass''stylus') } } Generate loaders for standalone style files (outside of .vue) exports.styleLoaders = (options) { var output = [] exports.cssLoaders(options) for (var extension in loaders) { var loader = loaders[extension] output.push({ test: new RegExp('\\.' + extension + '$' 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 = () { var entryFiles = glob.sync(PAGE_PATH + '/*/*.js') var map = {} entryFiles.forEach((filePath) => { var filename = filePath.substring(filePath.lastIndexOf('\/') + 1,filePath.lastIndexOf('.')) map[filename] = filePath }) map } 多页面输出配置 与上面的多页面入口配置相同,读取pages文件夹下的对应的html后缀文件,然后放入数组中 exports.htmlPlugin = () { let entryHtml = glob.sync(PAGE_PATH + '/*/*.html') let arr = [] entryHtml.forEach((filePath) => { let filename = filePath.substring(filePath.lastIndexOf('\/') + 1,1)">)) let conf = 模板来源 template: filePath, 文件名称 filename: filename + '.html' 页面模板需要加对应的js脚本,如果不加这行则每个页面都会引入所有的js脚本 chunks: ['manifest','vendor' } if (process.env.NODE_ENV === 'production') { conf = merge(conf,{ minify: { removeComments: },chunksSortMode: 'dependency' }) } arr.push(new HtmlWebpackPlugin(conf)) }) arr } 这里是添加的部分 ---------------------------- 结束 */
webpack.base.conf.js 文件
webpack.base.conf.js 文件 var utils = require('./utils'var vueLoaderConfig = require('./vue-loader.conf') resolve(dir) { return path.join(__dirname,'..' { 修改部分 ---------------- 开始 */ entry: utils.entries(),1)"> 修改部分 ---------------- 结束 output: { path: config.build.assetsRoot,filename: '[name].js' config.build.assetsPublicPath : config.dev.assetsPublicPath },resolve: { extensions: ['.js','.vue','.json'],alias: { 'vue$': 'vue/dist/vue.esm.js''pages': resolve('src/pages') } },module: { rules: [{ test: /\.vue$//\.js$/'src'),resolve('test')] },{ test: /\.(png|jpe?g|gif|svg)(\?.*)?$/10000) } },{ test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/) } } ] } }
webpack.dev.conf.js 文件
var webpack = require('webpack'var baseWebpackConfig = require('./webpack.base.conf'var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin' add hot-reload related code to entry chunks Object.keys(baseWebpackConfig.entry).forEach( (name) { baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) }) module.exports = merge(baseWebpackConfig,{ module: { rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) },1)"> cheap-module-eval-source-map is faster for development devtool: '#cheap-module-eval-source-map' webpack.DefinePlugin({ 'process.env': config.dev.env }),1)"> https://github.com/glenjamin/webpack-hot-middleware#installation--usage webpack.HotModuleReplacementPlugin(),1)"> webpack.NoEmitOnErrorsPlugin(),1)"> https://github.com/ampedandwired/html-webpack-plugin 注释这个区域的文件 ------------- 开始 */ new HtmlWebpackPlugin({ filename: 'index.html', template: 'index.html',1)"> inject: true 注释这个区域的文件 ------------- 结束 FriendlyErrorsPlugin() 添加 .concat(utils.htmlPlugin()) ------------------ ].concat(utils.htmlPlugin()) })
webpack.prod.conf.js 文件
var CopyWebpackPlugin = require('copy-webpack-plugin'var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin'var env = config.build.env var webpackConfig = }) },devtool: config.build.productionSourceMap ? '#source-map' : false'js/[id].[chunkhash].js') },1)"> http://vuejs.github.io/vue-loader/en/workflow/production.html : env }),1)"> webpack.optimize.UglifyJsPlugin({ compress: { warnings: },sourceMap: }),1)"> extract css into its own file ExtractTextPlugin({ filename: utils.assetsPath('css/[name].[contenthash].css') }),1)"> Compress extracted CSS. We are using this plugin so that possible duplicated CSS from different components can be deduped. OptimizeCSSPlugin({ cssProcessorOptions: { safe: } }),1)"> 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 注释这个区域的内容 ---------------------- 开始 filename: config.build.index,1)"> inject: true,1)"> minify: { removeComments: true,1)"> collapseWhitespace: true,1)"> removeAttributeQuotes: true // more options: // https://github.com/kangax/html-minifier#options-quick-reference },1)"> // necessary to consistently work with multiple chunks via CommonsChunkPlugin chunksSortMode: 'dependency' 注释这个区域的内容 ---------------------- 结束 */ split vendor js into its own file webpack.optimize.CommonsChunkPlugin({ name: 'vendor' (module,count) { any required modules inside node_modules are extracted to vendor ( module.resource && /\.js$/.test(module.resource) && module.resource.indexOf( path.join(__dirname,'../node_modules') ) === 0 ) } }),1)"> extract webpack runtime and module manifest to its own file in order to prevent vendor hash from being updated whenever app bundle is updated webpack.optimize.CommonsChunkPlugin({ name: 'manifest'] }),1)"> copy custom static assets CopyWebpackPlugin([{ from: path.resolve(__dirname,'../static'] }]) 该位置添加 .concat(utils.htmlPlugin()) ------------------- ].concat(utils.htmlPlugin()) }) (config.build.productionGzip) { var CompressionWebpackPlugin = require('compression-webpack-plugin') webpackConfig.plugins.push( CompressionWebpackPlugin({ asset: '[path].gz[query]' RegExp( '\\.(' + config.build.productionGzipExtensions.join('|') + ')$' ),threshold: 10240 }) ) } (config.build.bundleAnalyzerReport) { var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin webpackConfig.plugins.push( BundleAnalyzerPlugin()) } 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。
一般都认为这样写:
<!-- index.html --> <a href='../cell/cell.html'></a>
但这样写,不论是在开发环境还是最后测试,都会报404,找不到这个页面。
改成这样既可:
='cell.html'>
如果想跳转到另外一个路由配置的某个模块,如账号中心,如下例子:
class="home_account" href="login.html#/inner/acount/acountCenter">{{userInfo.phone}}</>