摒棄gulp.js+require.js,使用webpack配置多頁面web項目

不想看下面廢話的,能夠直接看這裏css

前言

這兩週負責公司前端基礎工程的建設。主要作了兩套方案,一套是基於vue的單頁應用,還有一套就是多頁應用。對於vue單頁這塊是沒什麼問題的,直接用vue-cli生成項目,再懟上vue全家桶以及一些工具函數,而後規範一下目錄結構啥的基本就ok了。html

麻煩的是原先使用 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 一步到位。嗯仍是不能偷懶啊。vue

項目結構

├── 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裏的命令和依賴node

script:android

"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"
    }

依賴:webpack

"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 配置:ios

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 來獲取的:git

/*獲取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:github

// 入口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

相關文章
相關標籤/搜索