最近在作vue項目改形成多頁面應用的優化,下面是我分享的方法css
一、改造本身的項目結構
這是以前的項目結構html
改造後:vue
在這裏:
assets 和 components 文件夾不變,pages裏面放咱們的多頁面node
每一個頁面下必須包含的文件是 html / js / vue,是文件入口,若是該頁面下包含路由,狀態管理,接口請求也放在該目錄下;webpack
二、vue項目改形成多頁面項目最主要的是對webpack配置的修改。
在這一步裏咱們須要改動的文件都在build文件下,分別是:git
utils.js
webpack.base.conf.js
webpack.dev.conf.js
webpack.prod.conf.jsgithub
utils.jsweb
// 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 = 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 function generateLoaders(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) { 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) { var output = [] var loaders = exports.cssLoaders(options) for (var extension in loaders) { var 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 } /* 這裏是添加的部分 ---------------------------- 結束 */ ```
webpack.base.conf.js 文件json
// webpack.base.conf.js 文件 var path = require('path') var utils = require('./utils') var config = require('../config') var vueLoaderConfig = require('./vue-loader.conf') function resolve(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: [ new webpack.DefinePlugin({ 'process.env': config.dev.env }), // https://github.com/glenjamin/webpack-hot-middleware#installation--usage new webpack.HotModuleReplacementPlugin(), new webpack.NoEmitOnErrorsPlugin(), // https://github.com/ampedandwired/html-webpack-plugin /* 註釋這個區域的文件 ------------- 開始 */ // new HtmlWebpackPlugin({ // filename: 'index.html', // template: 'index.html', // inject: true // }), /* 註釋這個區域的文件 ------------- 結束 */ new FriendlyErrorsPlugin() /* 添加 .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.env var 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 new webpack.DefinePlugin({ 'process.env': env }), new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false }, sourceMap: true }), // extract css into its own file new ExtractTextPlugin({ 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. new OptimizeCSSPlugin({ 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 new webpack.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 new webpack.optimize.CommonsChunkPlugin({ name: 'manifest', chunks: ['vendor'] }), // copy custom static assets new CopyWebpackPlugin([{ 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( new CompressionWebpackPlugin({ asset: '[path].gz[query]', algorithm: 'gzip', test: new RegExp( '\\.(' + config.build.productionGzipExtensions.join('|') + ')$' ), threshold: 10240, minRatio: 0.8 }) ) } if (config.build.bundleAnalyzerReport) { var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin webpackConfig.plugins.push(new BundleAnalyzerPlugin()) } module.exports = webpackConfig
至此webpack的配置就改完了,但仍是有些小細節上的須要修改。
頁面
.js文件裏面要用render函數
好比:
import Vue from 'Vue' import cell from './cell.vue' /* eslint-disable no-new */ new Vue({ el: '#app', render: h => h(cell) })
還須要注意的是:
config文件夾下的index.js 裏面的路徑須要改變
build部分 路徑要改爲 ./
dev部分:的路徑
(我在這裏不當心把路徑給改了,run dev 打開後獲取不了頁面)
到這裏就改造完成了,趕快打包試一下吧~~~