美文网首页前端开发Web前端之路让前端飞
摒弃gulp.js+require.js,使用webpack配置

摒弃gulp.js+require.js,使用webpack配置

作者: 赵的拇指 | 来源:发表于2017-10-28 17:32 被阅读118次

    不想看下面废话的,可以直接看这里

    前言

    这两周负责公司前端基础工程的建设。主要做了两套方案,一套是基于vue的单页应用,还有一套就是多页应用。对于vue单页这块是没什么问题的,直接用vue-cli生成项目,再怼上vue全家桶以及一些工具函数,然后规范一下目录结构啥的基本就ok了。

    麻烦的是原先使用 gulp+require.js 这个方案。这个在我来公司之前就已经存在,当初我刚来的时候使用的是 grunt+require.js+jQuery(zepto)+sass ,然后我用这个第一次写项目时,实在受不了了 grunt 的缓慢,就换成了 gulp 。这次对于这个方案我本来也只是想小改一下,因为这个方案用着还行,我就想加个 ES6 把 require.js 干掉,然后还有些其他小问题的修复就好了。

    然后按照想法开始给 gulp 任务里加上 babel 处理 ES6 。然后运行,发现如果使用了ES6中的 module,通过 importexport 进行模块化开发,那么通过babel转码后,importexport会被转成符合CMD规范的 requireexports 等,但是浏览器还是跑不了,这时还需要 bowserify 、webpack 、rollup 之类的对代码再次进行构建。这太麻烦了,还不如使用 webpack 一步到位。嗯还是不能偷懒啊。

    项目结构

    ├── build # webpack处理目录
    │   ├── build.js
    │   ├── config.js
    │   ├── run-env.js
    │   ├── utils.js
    │   ├── webpack.config.base.js
    │   ├── webpack.config.dev.js
    │   └── webpack.config.prod.js
    ├── dist # 打包之后的文件目录
    │   ├── commons.bundle.js
    │   ├── css
    │   │   ├── index.eb8584e93d4fbcbec235.css
    │   │   └── test.eb8584e93d4fbcbec235.css
    │   ├── img
    │   │   └── test.d7a9b40f5bed4003db2585ba1bf24d86.jpg
    │   ├── index.html
    │   ├── js
    │   │   ├── index.bundle.eb8584e93d4fbcbec235.js
    │   │   └── test.bundle.eb8584e93d4fbcbec235.js
    │   └── test.html
    ├── src # 源文件
    │   ├── css
    │   │   ├── base.scss
    │   │   ├── index.scss
    │   │   ├── test.scss
    │   │   └── var.scss
    │   ├── html
    │   │   ├── index.html
    │   │   └── test.html
    │   ├── img
    │   │   └── test.jpg
    │   └── js
    │       ├── app
    │       │   ├── index.js
    │       │   └── test.js
    │       ├── base
    │       └── component
    ├── webpack.config.js # webpack入口
    

    package.json

    先看下package.json里的命令和依赖

    script:

    "scripts": {
            "init-page": "node ./init-page.js",
            "dev": "export NODE_ENV=development && webpack-dev-server --open",
            "build": "export NODE_ENV=production && node ./build/build.js"
        }
    

    依赖:

    "devDependencies": {
            "babel-core": "^6.26.0",
            "babel-loader": "^7.1.2",
            "babel-preset-env": "^1.6.0",
            "clean-webpack-plugin": "^0.1.17",
            "css-loader": "^0.28.7",
            "eslint": "^4.10.0",
            "eslint-config-standard": "^10.2.1",
            "eslint-plugin-html": "^3.2.2",
            "eslint-plugin-import": "^2.8.0",
            "eslint-plugin-node": "^5.2.1",
            "eslint-plugin-promise": "^3.6.0",
            "eslint-plugin-standard": "^3.0.1",
            "exports-loader": "^0.6.4",
            "extract-text-webpack-plugin": "^3.0.1",
            "file-loader": "^1.1.5",
            "html-webpack-plugin": "^2.30.1",
            "html-withimg-loader": "^0.1.16",
            "node-sass": "^4.5.3",
            "postcss-loader": "^2.0.7",
            "preprocess-loader": "^0.2.2",
            "sass-loader": "^6.0.6",
            "script-loader": "^0.7.2",
            "style-loader": "^0.19.0",
            "url-loader": "^0.6.2",
            "webpack": "^3.7.1",
            "webpack-dev-server": "^2.9.1",
            "webpack-merge": "^4.1.0"
        }
    

    webpack 入口配置

    webpack的入口文件是 webpack.config.js ,在这个文件中就是根据命令执行相应的 webpack 配置:

    const env = process.env.NODE_ENV === 'production' ? 'prod' : 'dev';
    // 根据环境执行指定文件
    module.exports = require(`./build/webpack.config.${env}.js`);
    

    webpack 基础配置

    webpack.base.config.js 中就是webpack的一些常规处理包括loader以及一些文件清理啥的。由于要配置的是多页应用所以对于入口文件的处理,这也是比较麻烦的一点。对于多入口文件的处理使用html-webpack-plugin这个插件。
    在使用之前需要先获取所有的html文件名称,这个我是使用 node 的 fs 以及 path api 来获取的:

    /*获取html文件名*/
    module.exports = {
        getFileNameList(path) {
            let fileList = [];
            let dirList = fs.readdirSync(path);
            dirList.forEach(item => {
                if (item.indexOf('html') > -1) {
                    fileList.push(item.split('.')[0]);
                }
            });
            return fileList;
        }
    };
    

    然后再处理webpack入口以及 html plugin:

    // 入口html数组
    let HTMLDirs = utils.getFileNameList('./src/html');
    
    let HTMLPlugins = [];
    
    // 入口文件集合处理
    let entries = {};
    HTMLDirs.forEach(page => {
        const htmlPlugin = new HTMLWebpackPlugin({
            filename: `${page}.html`,
            template: path.resolve(__dirname, `../src/html/${page}.html`),
            chunks: [page, 'commons']
        });
        HTMLPlugins.push(htmlPlugin);
        entries[page] = path.resolve(__dirname, `../src/js/app/${page}.js`);
    });
    

    相关webpack配置,具体配置见github

    // webpack配置
    module.exports = {
        entry: entries,
        ...
        plugins: [
            // 自动生成 HTML 插件
            ...HTMLPlugins
        ]
    };
    

    最复杂的麻烦的都在base中干完了,本地开发和打包build只要做一些简单的处理就ok了

    webpack 本地开发文件配置与打包线上文件配置

    本地与线上的配置文件,需要先合并 base 里的配置(使用 webpack-merge 可以处理这个工作),然后做一下简单处理即可。

    // dev
    module.exports = webpackMerge(webpackBase, {
        devServer: {
            contentBase: config.devServerOutputPath,
            overlay: {
                errors: true,
                warnings: true
            }
        }
    });
    
    // prod
    module.exports = webpackMerge(webpackBase, {
        devtool: false,
        plugins: [
            // 代码压缩
            new webpack.optimize.UglifyJsPlugin({
                compress: {
                    warnings: false
                }
            }),
            // 提取公共 JavaScript 代码
            new webpack.optimize.CommonsChunkPlugin({
                // chunk 名为 commons
                name: 'commons',
                filename: '[name].bundle.js'
            })
        ]
    });
    
    

    zepto 等未模块化的库的处理

    在处理zepto之类的未模块化的库的时候我采取的方案是cdn加载,然后webpack配置里加上外部扩展即可
    externals 可以防止将某些 import 的包(package)打包到 bundle 中,而是在运行时(runtime)再去从外部获取这些扩展依赖(external dependencies))

    externals: {
        'zepto': '$'
    }
    

    preprocess

    之前这套方案是要做三端的H5以及嵌入android、ios的webview,所以需要根据平台做一些特殊处理。gulp里有gulp-preprocess可以比较好的处理,在webpack中可以使用 preprocess-loader 来处理。

    {
        test: /\.(html|js|css|scss)$/,
        loader: `preprocess-loader?${runEnv}`
    }
    

    后记

    暂时只做了这些,这套工具还没有正式投入使用估计会有挺多问题的。后续有问题会继续补充。

    感谢您的阅读,本文由 赵的拇指 版权所有。原文地址: https://www.zhaofinger.com/detail/11

    相关文章

      网友评论

        本文标题:摒弃gulp.js+require.js,使用webpack配置

        本文链接:https://www.haomeiwen.com/subject/nouspxtx.html