解决webpack多页面内存溢出的方法示例


Posted in Javascript onOctober 08, 2019

因为自己的项目是基于vue-cli3进行开发,所以这里只讨论这种情况下的解决办法

在进行多页面开发的时候,项目刚开始阶段,因为文件较少,所以代码编译速度还行,但是随着项目逐渐增大,webpack编译的速度越来越慢,并且经常出现内存溢出的情况。

下面就是几种尝试的方法,加快编译的速度

增加Node运行内存

在Node中通过JavaScript使用内存时只能使用部分内存(64位系统下约为1.4 GB,32位系统下约为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最近在抓紧学习,会持续更新文章,希望大家多多关注。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javaScript 判断字符串是否为数字的简单方法
Jul 25 Javascript
javascript面向对象编程(一) 实例代码
Jun 25 Javascript
一个很有趣3D球状标签云兼容IE8
Aug 22 Javascript
javascript结合CSS实现苹果开关按钮特效
Apr 07 Javascript
JQuery控制radio选中和不选中方法总结
Apr 15 Javascript
JS实现的网页背景闪电闪烁效果代码
Oct 17 Javascript
JS获取浮动(float)元素的style.left值为空的快速解决办法
Feb 19 Javascript
Vue.js学习笔记之修饰符详解
Jul 25 Javascript
jquery.rotate.js实现可选抽奖次数和中奖内容的转盘抽奖代码
Aug 23 jQuery
客户端(vue框架)与服务器(koa框架)通信及服务器跨域配置详解
Aug 26 Javascript
Vue-cropper 图片裁剪的基本原理及思路讲解
Apr 17 Javascript
Node绑定全局TraceID的实现方法
Nov 14 Javascript
javascript简单实现深浅拷贝过程详解
Oct 08 #Javascript
webpack HappyPack实战详解
Oct 08 #Javascript
简单了解vue中的v-if和v-show的区别
Oct 08 #Javascript
在Koa.js中实现文件上传的接口功能
Oct 08 #Javascript
vue-cli和v-charts实现可视化图表过程解析
Oct 08 #Javascript
vue路由传参页面刷新参数丢失问题解决方案
Oct 08 #Javascript
vux-scroller实现移动端上拉加载功能过程解析
Oct 08 #Javascript
You might like
php编程实现获取excel文档内容的代码实例
2011/06/28 PHP
DOM XPATH获取img src值的query
2013/09/23 PHP
爱恋千雪-US-AscII加密解密工具(网页加密)下载
2007/06/06 Javascript
整理8个很棒的 jQuery 倒计时插件和教程
2011/12/12 Javascript
window.open关于浏览器拦截问题分析及解决方法
2013/02/05 Javascript
jQuery.extend()的实现方式详解及实例
2013/06/29 Javascript
页面定时刷新(1秒刷新一次)
2013/11/22 Javascript
jQuery中delegate与on的用法与区别示例介绍
2013/12/20 Javascript
jQuery实现自动滚动到页面顶端的方法
2015/05/22 Javascript
详解js中class的多种函数封装方法
2016/01/03 Javascript
浅谈Javascript数组(推荐)
2016/05/17 Javascript
jquery实现左右滑动式轮播图
2017/03/02 Javascript
JavaScript实现滑动导航栏效果
2017/08/30 Javascript
react配合antd组件实现的管理系统示例代码
2018/04/24 Javascript
详解超简单的react服务器渲染(ssr)入坑指南
2019/02/28 Javascript
微信小程序开发实现的IP地址查询功能示例
2019/03/28 Javascript
vue router 用户登陆功能的实例代码
2019/04/24 Javascript
vue实现分页栏效果
2019/06/28 Javascript
nest.js 使用express需要提供多个静态目录的操作方法
2019/10/24 Javascript
js实现带搜索功能的下拉框
2020/01/11 Javascript
bootstrap实现tab选项卡切换
2020/08/09 Javascript
Vue项目如何引入bootstrap、elementUI、echarts
2020/11/26 Vue.js
Python中实现变量赋值传递时的引用和拷贝方法
2018/04/29 Python
django将图片上传数据库后在前端显式的方法
2018/05/25 Python
利用Pycharm断点调试Python程序的方法
2018/11/29 Python
对python列表里的字典元素去重方法详解
2019/01/21 Python
python实现的读取网页并分词功能示例
2019/10/29 Python
使用matlab 判断两个矩阵是否相等的实例
2020/05/11 Python
Python填充任意颜色,不同算法时间差异分析说明
2020/05/16 Python
基于Python快速处理PDF表格数据
2020/06/03 Python
护理专业毕业生自我鉴定
2013/10/08 职场文书
2014年征兵标语
2014/06/20 职场文书
酒店人事主管岗位职责
2015/04/11 职场文书
2015年办税服务厅工作总结
2015/07/23 职场文书
自考生自我评价
2019/06/21 职场文书
PostgreSQL自动更新时间戳实例代码
2021/11/27 PostgreSQL