2 Star 4 Fork 1

三人行 / appindex-pcindex

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
贡献代码
同步代码
取消
提示: 由于 Git 不支持空文件夾,创建文件夹后会生成空的 .keep 文件
Loading...
README

appindex-pcindex

介绍

vue 多页面(pc, 移动)切换包括 js 对应打包,完美方案

软件架构

软件架构说明

安装教程

git clone 链接

npm install

npm run dev

文档说明

1 目标

在不改变 vue 路由的前提下,自动切换与设备匹配的页面 不同设备的页面引入的模块代码要进行分离,避免引入无关代码,影响效率

2 思路

不同的设备可能是完全不同的页面,不只是页面设计不同,使用的前端框架也可能不同,需要引入的第三方模块可能差异很大,所以要从根本上进行分离,只能采用不同的 html 作为入口,再通过一个统一入口页面进行设备识别,实现页面自动跳转。这实际是一个多页面结构。由于原来通过 vue 脚手架生成的工程是一个单页面结构,所有需要对 webpack 打包设置和目录结构进行调整。

调整目录结构:为了完全分离不同设备的页面,在 src 下新建 pages 目录,其下再按设备建立页面目录,比如 pages/pc、 pages/mobile 等 调整 webpack 打包配置

1) 入口(build/webpack.base.conf.js 中的 entry)设置多入口,入口 js 为相应设备页面目录下的 main.js。

2) 超文本插件(build/webpack.dev.conf.js 和 build/webpack.prod.conf.js -> plugins ->HtmlWebpackPlugin)设置多个 HtmlWebpackPlugin,每个对应一个设备页面目录下的 index.html。

3) 第三方模块打包(build/webpack.prod.conf.js -> plugins -> CommonsChunkPlugin)(可选)如果需要对依赖的第三方模块进行分离,可以设置多个 CommonsChunkPlugin,每个对应一个设备页面的第三方模块。由于这个设置并不会影响实际加载的文件总大小,所以该设置为可选。

3. 方案

3.1. 调整目录结构

建立下面的目录结构:

src

 |- pages
 |  |- pc
 |  |  |- assets
 |  |  |- components
 |  |  |- router
 |  |  |- App.vue
 |  |  |- index.html
 |  |  |- main.js
 |  |-mobile
 |  |  |- assets
 |  |  |- components
 |  |  |- router
 |  |  |- App.vue
 |  |  |- index.html
 |  |  |- main.js
 |- main.js

其实就是把原来 src 下的目录结构移到“src/pages/<设备类型>/”下面,并增加 index.html 入口页面模板,index.html 可以从工程目录下复制。删除原来 src 下面的目录,只留下 main.js 文件和新建的 pages 目录。

3.2. 修改 main.js, 实现设备识别和页面切换

修改 src/main.js,清空原有所有内容,替换为以下代码:

const isPc = () => {
return !isMobile()
}

const isMobile = () => {
return /(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i.test(navigator.userAgent)
}

const params = window.location.search + window.location.hash

if (isPc()) {
window.location.href = 'pc_index.html' + params
} else if (isMobile()) {
window.location.href = 'mobile_index.html' + params
}

这里面页面的名称要根据设备名称命名,与src/pages下面的目录名称一致。

3.3. 为webpack设置多入口

在build/utils.js中增加以下代码:

var glob = require('glob')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var merge = require('webpack-merge')
//页面根目录
var PAGE_ROOT_PATH = path.resolve(__dirname, '../src/pages')
//取页面清单
function getPages() {
  let entryHtmlFiles = glob.sync(PAGE_ROOT_PATH + '/*/index.html')
  let pages = []
  entryHtmlFiles.forEach((filePath) => {
    let pagePath = filePath.substring(0, filePath.lastIndexOf('\/'))
    let pageName = pagePath.substring(pagePath.lastIndexOf('\/') + 1)
    pages.push(pageName)
  })
  return pages
}
//生成入口
exports.entries = function () {
  var map = {}
  getPages().forEach((pageName) => {
    let filePath = PAGE_ROOT_PATH + '/' + pageName + '/main.js'
    map['app_' + pageName] = filePath
  })
  return map
}

3.3.2. 设置多入口

在build/webpack.base.conf.js中修改entry:

module.exports = {
    ...
    entry: Object.assign({app: './src/main.js'}, utils.entries()),
    ...
}

3.4. 为webpack设置多个页面生成插件

3.4.1. 生成页面插件

在build/utils.js中增加以下代码:(在本文3.3.1基础上修改)

exports.htmlPlugins = function () {
  let plugins = []
  getPages().forEach((pageName) => {
    let templateFilePath = PAGE_ROOT_PATH + '/' + pageName + '/index.html'
    let outputFileName = pageName + '_index.html'
    let conf = {
      template: templateFilePath,
      filename: outputFileName,
      chunks: ['manifest', 'vendor', 'vendor_' + pageName, 'app_' + pageName],
      inject: true
    }
    if (process.env.NODE_ENV === 'production') {
      conf = merge(conf, {
        minify: {
          removeComments: true,
          collapseWhitespace: true,
          removeAttributeQuotes: true
        },
        chunksSortMode: 'dependency'
      })
    }
    plugins.push(new HtmlWebpackPlugin(conf))
  })
  return plugins
}

3.4.2. 设置页面插件

修改bin/webpack.dev.conf.js:

plugins: [
    ...
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: 'index.html',
      chunks: ['app'],  //修改这里
      inject: true
    }),
    ...
].concat(utils.htmlPlugins()) //修改这里

修改bin/webpack.prod.conf.js:

plugins: [
    ...
    new HtmlWebpackPlugin({
      filename: config.build.index,
      template: 'index.html',
      chunks: ['app'], //修改这里
      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'
    }),
    ...
].concat(utils.htmlPlugins()) //修改这里

3.5. 分离各个页面引用的第三方模块(可选步骤)

修改bin/webpack.prod.conf.js:

plugins: [
    ...
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor_pc',
      chunks: ['app_pc'],
      minChunks(module) {
        console.log(module.resource)
        return module.resource && /\.js$/.test(module.resource) && module.resource.indexOf(path.join(__dirname, '../node_modules')) == 0
      }
    }),

    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor_mobile',
      chunks: ['app_mobile'],
      minChunks(module) {
        return module.resource && /\.js$/.test(module.resource) && module.resource.indexOf(path.join(__dirname, '../node_modules')) == 0
      }
    }),

    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      chunks: ['vendor_pc', 'vendor_mobile'],
      minChunks: 2
    }),
    ...
]

注意:三段创建CommonsChunkPlugin插件实例的代码顺序不能颠倒,要保证设备页面入口的vendor在公共vendor之前。chunk名称要与pages下面目录名称一致

原理解释:CommonsChunkPlugin根据创建时的选项,自动提取公共代码,生成独立的js文件(chunk)。 选项及作用如下:

name:可以是已经存在的chunk(一般指入口文件)对应的name,那么就会把公共模块代码合并到这个chunk上;否则,会创建名字为name的commons chunk进行合并。

filename:指定commons chunk的文件名。

chunks:指定source chunk,即指定从哪些chunk当中去找公共模块,省略该选项的时候,默认就是entry chunks。

minChunks:既可以是数字,也可以是函数,还可以是Infinity。
数字:模块被多少个chunk公共引用才被抽取出来成为commons chunk。

函数:接受 (module, count) 两个参数,返回一个布尔值,你可以在函数内进行你规定好的逻辑来决定某个模块是否提取成为commons chunk。

Infinity:只有当入口文件(entry chunks) >= 3 才生效,用来在第三方库中分离自定义的公共模块。

上面的设置,实际完成下面步骤: 1) 从app_pc这个入口里面提取第三方模块,生成vendor_pc。 2) 从app_mobile这个入口里面提取第三方模块,生成vendor_mobile。 3) 从vendor_pc和vendor_mobile中提取公共模块,生成vendor。

4. 代码影响

src下代码全部移到了src/pages/<设备名称>下面,所以如果使用了相对路径,则不会有问题。
但是如果使用了路径别名“@”(代表src),则会受到影响。建议把用到“@”的地方更换为相对路径。

空文件

简介

vue 多页面(pc, 移动)切换包括js对应打包,完美方案 展开 收起
取消

发行版

暂无发行版

贡献者

全部

近期动态

加载更多
不能加载更多了
1
https://gitee.com/xuqiang001/appindex-pcindex.git
git@gitee.com:xuqiang001/appindex-pcindex.git
xuqiang001
appindex-pcindex
appindex-pcindex
master

搜索帮助

53164aa7 5694891 3bd8fe86 5694891