解决webapck多页面内存溢出

因为自己的项目是基于vue-cli3进行开发,所以这里只讨论这种情况下的解决办法
在进行多页面开发的时候,项目刚开始阶段,因为文件较少,所以代码编译速度还行,但是随着项目逐渐增大,webpack编译的速度越来越慢,并且经常出现内存溢出的情况。
下面就是几种尝试的方法,加快编译的速度

增加Node运行内存

Node中通过JavaScript使用内存时只能使用部分内存(64位系统下约为1.4 GB32位系统下约为0.7 GB)。所以不管电脑实际的运行内存是多少,Node在运行代码编译的时候,使用内存大小不会发生变化。这样就可能导致因为原有的内存不够,导致内存溢出。所以可以增加Node的运行内存,下面是两种方法

更改cmd

node_modules/.bin/vue-cli-server.cmd把下面代码复制上去

@IF EXIST "%~dp0\node.exe" (
  "%~dp0\node.exe" --max_old_space_size=4096 "%~dp0\..\@vue\cli-service\bin\vue-cli-service.js" %*
) ELSE (
  @SETLOCAL
  @SET PATHEXT=%PATHEXT:;.JS;=;%
  node --max_old_space_size=4096  "%~dp0\..\@vue\cli-service\bin\vue-cli-service.js" %*
)

更改package.json

把启动Node服务的更改下:

node --max_old_space_size=4096 node_modules/@vue/cli-service/bin/vue-cli-service.js serve

本质上没啥区别,都是通过强行增加Node的运行内存,来解决内存溢出的问题。但是这种方法不治本,虽然不会造成内存溢出,但是编译速度还是挺慢的,编译完成还是需要等很久。

配置需要编译的文件

这种就是按需配置需要编译的文件,为什么出现内存溢出,本质上还是因为需要编译的文件太多了,那我们就可以减少需要编译的页面就可以解决这个问题。
首先所有的页面配置都是放在page.config.js,如果我们需要对某些特定页面进行配置,就需要过滤所有的页面,获取需要编译的页面,下面是编译文件的写法

const path = require('path');
const fs = require('fs');
const pages = require('../pages.config');

const params = JSON.parse(process.env.npm_config_argv).original;
const buildPath = params[params.length - 1].match(/[a-zA-Z0-9]+/)[0] || '';

let buildConfig = {
  pages: [],
};


if (!/(test|online|serve)/gi.test(buildPath)) {
  const configJsPath = path.resolve(__dirname, `${buildPath}.js`);

  // 如果该路径存在
  if (fs.existsSync(configJsPath)) {
    // eslint-disable-next-line import/no-dynamic-require
    buildConfig = require(configJsPath);
  } else if (pages[buildPath]) {
    buildConfig.pages = buildPath.split(',');
  } else {
    throw new Error('该路径不存在');
  }
} else {
  buildConfig = require('./default');
}
module.exports = buildConfig.pages;

大多数情况下,一个产品都是由多个业务线构成,每次可能需要更改的就是某一条业务线,就完全可以单独创建一个这条业务线的配置文件,然后再这个文件写入你需要编译的页面名称,就可以单独编译这个页面,或者说在调用通过传入的字符串来编译那些页面

使用webbpack-dev-serve钩子进行单独编译

在webpack进行热更新的时候,实际上是使用了webpack-dev-server这个的服务,然后是否有钩子能够给我们提供,如果我们访问哪个页面他就编译那个页面的代码。幸运的是找到,在devServer中存在这么一个钩子函数before, 那就可以在vue.config.js中修改

const compiledPages = [];
before(app) {
      app.get('*.html', (req, res, next) => {
        const result = req.url.match(/[^/]+?(?=\.)/);
        const pageName = result && result[0];
        const pagesName = Object.keys(multiPageConfig);

        if (pageName) {
          if (pagesName.includes(pageName)) {
            if (!compiledPages.includes(pageName)) {
              const page = multiPageConfig[pageName];
              fs.writeFileSync(`dev-entries/${pageName}.js`, `import '../${page.tempEntry}'; // eslint-disable-line`);
              compiledPages.push(pageName);
            }
          } else {
            // 没这个入口
            res.writeHead(200, { 'content-type': 'text/html; charset=utf-8' });
            res.end('<p style="font-size: 50px;">不存在的入口</p>');
          }
        }
        next();
      });
    },

multPageConfig是多页面的配置,在开发环境中,做了一下修改,配置如下:

{
    pageName: {
        entry: entryPath,
        chunks: [array]
    }
}
const fs = require('fs');
const util = require('util');

const outputFile = util.promisify(fs.writeFile);
async function main() {
  const tasks = [];
  if (!fs.lstatSync('dev-entries').isDirectory()) {
    fs.mkdirSync('dev-entries');
  }
  Object.keys(pages).forEach((key) => {
    const entry = `dev-entries/${key}.js`;
    pages[key].tempEntry = pages[key].entry; // 暂存真正的入口文件地址
    pages[key].entry = entry;
    tasks.push(outputFile(entry, ''));
  });
  await Promise.all(tasks);
}

if (process.env.NODE_ENV === 'development') {
  main();
}

module.exports = pages;

在上面文件中,我们首先需要更改多页面的配置,创建一个目录,包含所有的页面的js文件,但是需要注意的是这些文件都是空的文件,什么都没有,然后在vue.config.js中多页面的配置为

pages: multiPageConfig, // 配置多页应用

因为所有的页面js已经被置为空了,所以编译的速度非常快。然后再访问页面的时候,webpack已经拦截访问的页面,也就是需要更改的页面,这时候就手动往dev-entries目录下写入需要编译的文件,从而实现了访问某个页面就编译哪个页面的代码

升级html-webpack-plugin版本

多页面出现内存溢出的问题是因为在编译的时候,实际是一次更改,编译了多个文件,这是html-webpack-plugin的问题。因为没生成一个页面,就需要调用一下new htmlWebpackPlugin(),多个页面的时候内存就不够用了。所以改一下这个这个webpack插件的版本,升级到4.0.0-beta.8这个版本。然后再vue.config.js中添加下面的配置,这样也不会造成内存溢出。

const htmlPlugins = [];
Object.keys(multiPageConfig).forEach((key) => {
    htmlPlugins.push(multiPageConfig[key])
})
configureWebpack: {
    plugins: [
      ...htmlPlugins,
    ],
}

其他加快编译的技巧

webpack的插件还是很方便的,网上有啥happypack类似的插件。由于运行在 Node.js 之上的 Webpack 是单线程模型的,所以Webpack需要处理的事情需要一件一件的做,不能多件事一起做。
我们需要Webpack能同一时间处理多个任务,发挥多核CPU电脑的威力,HappyPack就能让Webpack 做到这点,它把任务分解给多个子进程去并发的执行,子进程处理完后再把结果发送给主进程。可能是我电脑太烂了,装上没啥太大的提升,具体使用方法可以参照这篇文章webpack优化之HappyPack 实战。还有一些细节的地方比如说有些包需要加入编译,但是一般我们在调试的时候只需要在chrome上进行调试,开发环境就不用加入编译,多处使用的代码单独打包,这些也就不说了,大家多多尝试

这几种解决多页面内存溢出的方法各有优缺点,读者可根据自己的项目自行决定使用哪种方法,可能有时还需要多种方式组合使用,就看看那个好使好用了。
解决这个问题顺便研究了一下webpack,配置果然博大精深,难怪市面有流传webpack配置工程师。推销一波自己的github最近在抓紧学习,会持续更新文章,希望大家多多关注。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,417评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,921评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,850评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,945评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,069评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,188评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,239评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,994评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,409评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,735评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,898评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,578评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,205评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,916评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,156评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,722评论 2 363
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,781评论 2 351

推荐阅读更多精彩内容

  • 写在开头 先说说为什么要写这篇文章, 最初的原因是组里的小朋友们看了webpack文档后, 表情都是这样的: (摘...
    Lefter阅读 5,283评论 4 31
  • 1. 新建一个文件夹,命名为 webpack-cli , webpack-cli 就是你的项目名,项目名建议使用小...
    鲁大师666阅读 1,471评论 1 3
  • 目录第1章 webpack简介 11.1 webpack是什么? 11.2 官网地址 21.3 为什么使用 web...
    lemonzoey阅读 1,731评论 0 1
  • 前言 本文主要从webpack4.x入手,会对平时常用的Webpack配置一一讲解,各个功能点都有对应的详细例子,...
    BetterChen阅读 1,946评论 0 3
  • 高登阔少的生活其实是很多香港人的写实,或者说是理想中想要达到的状态,酒有多好喝多好、车有多好开多好、妞胸有多大要多...
    夜未央0075460阅读 979评论 0 0