webpack 搭建vue多单页应用

为什么选择多单页

最近在核心业务上作了一项新的尝试,抛弃臃肿的PHP后端渲染的多页应用模式,全站改造单页应用。单页渲染在加载速度已经有了极大的提高,而且MVVM的模式使前端开发从繁琐的DOM操做中解放出来。为何考虑多单页模式,可综合多页和单页的优点,多页分离减小模块耦合,特别是应用复杂程度高时,此后也可在每一个单页里面尝试不一样的方案,利于拓展。本文是记录多单页实践的思路,脚手架vue-cli生成,详细的代码可参考demo,欢迎探讨。css

webpck搭建多单页

1.从入口文件entry提及

entry对象主要用于配置应用js入口文件,由模块名称为属性名(编译生成的js chunks的名称),以该js文件路径为属性值。以vue-cli搭建的单页应用为例,如下是初始配置。单页应用一般只有一个入口js文件(不包括其余公共js模块)。html

多单页应用则有多个js入口文件,entry也要配置多个入口,以下: webpack.base.conf.js前端

entry: {
    'index': './src/pages/main.js',// index.html 的入口文件
    'asset': './src/pages/asset/index.js',// 页面 asset.html 的入口文件
    'login': './src/pages/login/index.js',// 页面 login.html 的入口文件
  },
复制代码

当页面应用比较多的时候,能够引入glob模块,封装遍历函数。vue

//引入模块
var glob = require('glob');

//遍历函数
function getEntry(globPath) {
  var entries = {},
    basename, tmp, pathname;
    //下面的路径根据本身的目录结构修改,打印出来检查是否跟手写的一致
  glob.sync(globPath).forEach(function (entry) {
    basename = path.basename(entry, path.extname(entry));
    console.log("basename",basename);
    tmp = entry.split('/').splice(-3);
    pathname = tmp.splice(0, 1) + '/' + tmp.splice(0, 1) + '/' + basename; // 正确输出js和html的路径
    entries[pathname] = entry;
  });
  return entries;
}

//遍历pages路径下全部的main.js文件,全部的入口文件命名一致
var entries=getEntry('./src/pages/**/main.js');

// 传值
 entry: entries,
复制代码

关于entry更详细的内容可参考官网webpack

2. 多页应用还需修改HtmlWebpackPlugin配置页面渲染模版

webpack.dev.conf.jsgit

new HtmlWebpackPlugin(
    {
    //访问
      filename: 'pages/login/login.html',
      template: './src/pages/login/login.html',
      inject: true,
    //对应entry的chunks名称
      chunks:['login']
    }),
    new HtmlWebpackPlugin({
      filename: 'pages/asset/asset.html',
      template: './src/pages/asset/asset.html',
      inject: true,
      chunks:['asset']
    }),
复制代码

写成遍历: webpack.dev.conf.jses6

var pages = getEntry('./src/pages/**/*.html');
for (var pathname in pages) {
  // 配置生成的html文件,定义路径等
  var conf = {
    filename: pathname + '.html',
    template: pages[pathname],   // 模板路径
    inject: true              // js插入html尾部
  };
   if (pathname in baseWebpackConfig.entry) {
   //这里配置当前单页须要加载的chunks
    conf.chunks = ['manifest', 'vendor',pathname];
    conf.hash = true;
   }
  devWebpackConfig.plugins.push(new HtmlWebpackPlugin(conf));
}

//遍历函数
function getEntry(globPath) {
  var entries = {}, basename, tmp, pathname;

  glob.sync(globPath).forEach(function (entry) {
    basename = path.basename(entry, path.extname(entry));
    tmp = entry.split('/').splice(-3);
    pathname = tmp.splice(0, 1) + '/' + tmp.splice(0, 1) + '/' + basename; // 正确输出js和html的路径
    entries[pathname] = entry;
  });
  return entries;
}

复制代码

webpack构建多单页一些踩过的坑

  1. webpack打包后样式丢失 检查了很久发现是这2个插件冲突的问题,postCss loader 与 OptimizeCSSPlugin。 解决:去掉下列代码。
new OptimizeCSSPlugin({
      cssProcessorOptions: config.build.productionSourceMap
        ? { safe: true, map: { inline: false } }
        : { safe: true }
    }),
复制代码
  1. cannot find the element #app 单页页面加载了其余页面的入口文件,找不到对应的模版id致使。解决:在webpack配置,在前面HtmlWebpackPlugin配置只注入指定的chunks,这样就不会把其余页面的js也加载进来,致使找不到对应的html模版,也优化了加载。
if (pathname in baseWebpackConfig.entry) {
   //这里配置当前单页须要加载的chunks
    conf.chunks = ['manifest', 'vendor',pathname];
    conf.hash = true;
   }
复制代码
  1. 多单页命名问题 多单页面vue应用根元素的id不能相同, 不然会出现页面互相覆盖的问题。
new Vue({
    //根元素id
     el: '#app',
     components: { App },
     template: '<App/>'
    })
复制代码
  1. css 究竟是 import 仍是 require 两种都是模块引入的方式,import使es6规范,require是commonJS规范,须要注意的是import会有提高效果,可能出现import覆盖require样式。
require('/style.css');
import '/style.css';
复制代码
  1. 多单页之间vuex数据不能共享 单页应用之间vuex数据是不能共享的,由于其本质仍是多页应用。页面与页面之间的数据传递仍是要经过URL传参数或者经过缓存读取。这在必定程度上仍是增长了应用复杂度,因此在业务粒度的拆分上不能太细,尽可能保证在单个业务流程是在一个单页内,数据能够共享。github

  2. 考虑后续部署的问题 单页应用的部署很简单,只有一个html文件,采起多单页的方案,必需要提早跟运维沟通后续部署的问题,确保能实现平稳过渡。web

相关文章
相关标签/搜索