前言
平时工作中,公司项目没有做前后端分离,用的还是grunt+seajs比较旧的技术,基本是后端主导,前端只负责样式和效果,没办法有更多尝试。不过,前端技术日新月异,不能因为环境而局限自己想折腾的心,于是,在看过《基于webpack的前端工程化开发之多页站点篇》这篇文章之后,开始尝试。
github地址
webpack-multiplepage前端工程化多页面配置
项目依赖
npm init 初始化项目
npm install plugins --save-dev 安装依赖
package.json 依赖声明如下:"devDependencies": {
    "babel-core": "^6.26.0",                    // babel转译核心
    "babel-loader": "^7.1.2",                   // webpack使用转换ES6
    "babel-preset-env": "^1.6.1",               // 转码规则,按需转译
    "clean-webpack-plugin": "^0.1.18",          // 清理文件
    "copy-webpack-plugin": "^4.5.0",            // 复制文件
    "css-loader": "^0.28.9",                    // 将css装载到js
    "exports-loader": "^0.7.0",                 // 模块化,导出指定对象
    "extract-text-webpack-plugin": "^3.0.2",    // 将css分离成文件
    "file-loader": "^1.1.11",                   // 解析项目中的url引入
    "glob": "^7.1.2",                           // 根据模式匹配获取文件列表的node模块
    "html-loader": "^0.5.5",                    // 解析html文件的url
    "html-webpack-plugin": "^2.30.1",           // 处理html文件
    "node-sass": "^4.7.2",                      // 编译sass
    "sass-loader": "^6.0.7",                    // 将sass文件编译成css
    "script-loader": "^0.7.2",                  // 全局上下文执行一次 JS 脚本
    "style-loader": "^0.20.1",                  // css插入到页面的style标签
    "uglifyjs-webpack-plugin": "^1.1.8",        // 压缩js
    "url-loader": "^1.0.1",                     // url-loader封装了file-loader,将小图片生成dataURl
    "webpack": "^3.9.1",                        // webpack核心
    "webpack-dev-server": "^2.11.1",            // 热更新服务
    "webpack-merge": "^4.1.1"                   // 合并配置
}
npm run dev 执行开发环境,点击进入view文件夹
npm run build 执行打包发布
目录结构
- website  | 
项目目录有个局限性,就是开发目录里js中固定需要page文件夹放置页面级的js逻辑,与view中的.html文件一一对应。
开发
在src/js/page目录下建立index.js文件,在src/view目录下建立index.html文件。入口js和模板文件名对应。
index.js文件如下(这里已默认引入zepto,可直接使用$):
require("scss/variable.scss");  | 
index.html 内容如下:
<html>
<head>
    <meta charset="UTF-8" />
    <title>测试首页</title>
    <!--
        描述:head中无需再引入css以及facicon,webpack将根据入口JS文件的要求自动实现按需加载或者生成style标签
    -->
</head>
<body>
    <div class="gb-body"></div>
    <!--
        描述:body中同样无需单独引入JS文件,webpack会根据入口JS文件自动实现按需加载或者生成script标签,还可以生成对应的hash值
    -->
</body>
</html>
webpack配置
webpack配置base.js如下:
const path = require('path') // 引入node模块,获取路径  | 
webpack开发配置dev.js如下:
const webpack = require('webpack') // webpack  | 
webpack开发配置pro.js如下:
const path = require('path')  | 
根据模式匹配获取文件列表
结合《基于webpack的前端工程化开发之多页站点篇(一)》和《基于webpack的前端工程化开发之多页站点篇(二)》这两篇文章,应该很容易完成配置,但是我也发现一个问题,就是在view配置多级目录的时候类似view/question/question.html,打包配置会出问题,就仅局限于当前目录。
于是参考了kisnows 抹桥的Spart项目webpack配置,对入口和html生成配置做了调整。
getEntry.js如下:const glob = require('glob')
const path = require('path')
const cwd = process.cwd()
module.exports = function(jsPath){
    const entrys = {}
    const entryFiles = glob.sync(jsPath)
    const reg = /src\/(\S+)$/
    const fileReg = /src\/js\/(\S+).js$/
    entryFiles.forEach((v) => {
      const pathname = v.match(reg)[1]
      const filename = v.match(fileReg)[1]
      entrys[filename] = `./src/${pathname}`
    })
    return entrys
}
getEntry.js输出结果如下(举个栗子):{
    'page/about': './src/js/page/about.js',
    'page/index': './src/js/page/index.js',
    'page/question/question': './src/js/page/question/question.js'
}
getHtml.js如下:const glob = require('glob')
const path = require('path')
const cwd = process.cwd()
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = function (htmlPath){
    const pluginList = []
    const htmlFileList = glob.sync(htmlPath)
    const reg = /src\/(\S+)$/
    const fileReg = /src\/view\/(\S+).html$/
    htmlFileList.forEach((v)=>{
        const pathname = v.match(reg)[1]
        const filename = path.basename(v, path.extname(v))
        const shortname = v.match(fileReg)[1]
        pluginList.push(
            new HtmlWebpackPlugin({
                filename: `${pathname}`,
                template: `./src/${pathname}`,
                inject: 'body',
                chunks: ['vendors', `page/${shortname}`],
                hash: false,
                minify: process.env.NODE_ENV !== 'production' ? false : {
                  removeAttributeQuotes: true,
                  removeComments: true,
                  collapseWhitespace: true,
                  html5: true,
                  minifyCSS: true
                }
            })
        )
    })
    return pluginList
}
getHtml.js输出结果如下(举个栗子):[
    {
        filename: 'view/about.html',
        template: './src/view/about.html',
        inject: 'body',
        chunks: [ 'page/vendors', 'page/about' ],
        hash: false,
        minify: false
    },
    {
        filename: 'view/index.html',
        template: './src/view/index.html',
        inject: 'body',
        chunks: [ 'page/vendors', 'page/index' ],
        hash: false,
        minify: false
    },
    {
        filename: 'view/question/question.html',
        template: './src/view/question/question.html',
        inject: 'body',
        chunks: [ 'page/vendors', 'page/question/question' ],
        hash: false,
        minify: false
    }
]
如何在 webpack 中引入未模块化的库,如 Zepto
解决方法:
$ npm i -D script-loader exports-loader  | 
引入script-loader与exports-loader,然后参考以上的配置
NodeJs中process.cwd()与__dirname的区别
process.cwd() 是当前执行node命令时候的文件夹地址 ——工作目录,就是说 process.cwd() 返回的是当前Node.js进程执行时的工作目录
__dirname 是被执行的js文件的地址 ——文件所在目录,等同于 __filename 的 path.dirname()
参考
结语
其实在配置的过程中,有考虑到一个问题,就是后端童鞋不一定会用你这一套东西,就好像@抹桥说的那样,感觉这是为了用 webpack 而用 webpack 的节奏,还不如直接用gulp来的方便。可能确实也可能如此,但后面又想一想,思路通了就做一下吧,不能总是半途而废,于是就有了这篇文章。
配置的时候,参照了很多文章,自身水平有限,如有冒犯,请通知我!
谢谢您的品读,此处抛砖引玉,希望大家共同探讨学习。