webpack学习(三)

 

module:就是js的模块化webpack支持commonJS、ES6等模块化规范,简单来说就是你通过import语句引入的代码。

chunk: chunk是webpack根据功能拆分出来的,包含三种情况:

 

    1、你的项目入口(entry)

 

    2、通过import()动态引入的代码

 

    3、通过splitChunks拆分出来的代码

 

    chunk包含着module,可能是一对多也可能是一对一。

 

bundle:bundle是webpack打包之后的各个文件,一般就是和chunk是一对一的关系,bundle就是对chunk进行编译压缩打包等处理之后的产出。

 

一、优化

1.noParse: 不去解析属性值代表的库的依赖

表示在打包的时候不用再去深度解析某个第三方库中的依赖包,类似jq这类依赖库,一般会认为不会引用其他的包(特殊除外,自行判断)。所以,对于这类不引用其他的包的库,我们在打包的时候就没有必要去解析,这样能够增加打包速率。

 

 2.IgnorePlugin

表示忽略第三方包指定目录,让这些指定目录不要被打包进去

这是webpack自带的一个插件

比如我们要使用moment这个第三方依赖库,该库主要是对时间进行格式化,并且支持多个国家语言。在打包的时候,是会将所有语言都打包进去的。这样就导致包很大,打包速度又慢我们可以用这个插件忽略掉这些语言的打包,然后手动引入需要的语言包

 

plugins:[
        //webpack自带插件,从moment中引入的时候忽略掉语言
        new webpack.IgnorePlugin(/\.\/locale/,/moment/),
        new htmlWebpackPlugin({
            template: './public/index.html'
        })
    ]

 

index.js

import moment from 'moment'
//设置语言 忽略之后不再生效需要
// moment.locale('zh-cn')
//这时候需要手动引入需要的语言
import 'moment/locale/zh-cn'
let r = moment().endOf('day').fromNow() //距离今天结束还有几小时
console.log(r)

 

没有忽略语言包之前的大小

 

 忽略掉语言包之后的大小

3. DllPlugin 

这块没看懂,推荐这篇文章:https://www.cnblogs.com/tugenhua0707/p/9520780.html

4.Happypack 多进程打包

在使用 Webpack 对项目进行构建时,会对大量文件进行解析和处理。当文件数量变多之后,Webpack 构件速度就会变慢。由于运行在 Node.js 之上的 Webpack 是单线程模型的,所以 Webpack 需要处理的任务要一个一个进行操作。

而 Happypack 的作用就是将文件解析任务分解成多个子进程并发执行。子进程处理完任务后再将结果发送给主进程。所以可以大大提升 Webpack 的项目构件速度

由于 JavaScript 是单线程模型,要想发挥多核 CPU 的能力,只能通过多进程去实现,而无法通过多线程实现。

HappyPack 对file-loader、url-loader 支持的不友好,所以不建议对该loader使用。

 

之前打包js用的是这些loader

现在需要happypack

 

 

 

当项目体积庞大的时候用多进程打包会加快打包速率,小体积项目反而会降低打包速率,因为分配时进程本身也需要花费时间。

happypack原理请看这篇文章:https://segmentfault.com/a/1190000021037299?utm_source=tag-newest

5.webpack自带优化工具

  • tree-shaking 会自动将没用到的代码删除掉
test.js

function
sum (a, b) { return a+b } function minus (a, b) { return a-b } export default{ sum, minus }
index.js
import calc from './test' console.log(calc.sum(1,2))
此时我们只用到了sum方法,minus方法没有用到
在生产环境下打包会自动清除minus方法,这就是tree-shaking 会自动将没用到的代码删除掉
而且必须是以import引入的文件
要是以require引入的就不会清除
  • scope hosting 作用域提升  
let a = 1
 let b = 2
 let c = 3
 let d = a+b+c //webpack会自动省略可以简化的代码
console.log(d+'------')

 

 6.抽取公共代码

如果某个js文件被多个js代模块引用就可以将这个公共的代码块分割出去,打包成一个公共文件,代码分割是基于浏览器会缓存你的代码这一事实。每当你对某一文件做点改变,访问你站点的人们就要重新下载它。然而依赖却很少变动。如果你将(这些依赖)分离成单独的文件,访问者就无需多次重复下载它们了。

假设有两个页面indexother,现在这两个文件都需要引入a.js和b.j,如果不分割,这两个页面就都会有a.js的内容和b.js的内容,抽取之后这些公共内容将会放在一个common.js中,然后indexother各自的页面只包含自己的那部分内容,这个时候我们就可以这么配置了

entry: { 
      index: './src/index.js',
      other: './src/other.js'
    },
    output: {
        filename: '[name].js',
        path:path.resolve(__dirname,'dist')
    },
    module:{
      optimization:{ 
        splitChunks:{ //分割代码
          cacheGroups:{ //缓存组
            common:{ //公共模块
              chunks:'initial', //chunks有三个参数,initial表示只从入口模块进行拆分 async表示只从异步加载得模块(动态加载import())里面进行拆分 all表示以上两者都包括
              minSize:0, //表示在压缩前的最小模块大小
              minChunks:2 //只要超过2次以上引用就抽离
             },
          }
        }
      },

打包后的结果如下:

有时候我们还需要引入第三方模块,比如jquery等,这个时候也需要抽离这些第三方模块。如下配置:

entry: { 
      index: './src/index.js',
      other: './src/other.js'
    },
    output: {
        filename: '[name].js',
        path:path.resolve(__dirname,'dist')
    },
    module:{
      optimization:{ 
        splitChunks:{ //分割代码
          cacheGroups:{ //缓存组
            common:{ //公共模块
              chunks:'initial', //chunks有三个参数,initial表示只从入口模块进行拆分 async表示只从异步加载得模块(动态加载import())里面进行拆分 all表示以上两者都包括
              minSize:0, //表示在压缩前的最小模块大小
              minChunks:2 //只要超过2次以上引用就抽离
             },
             vendor:{ //抽离第三方模块
              priority:1, //表示先抽离第三方模块再抽离公共模块,不加这个的话第三方模块将和公共模块放在一起,不太好
              test:/node_modules/, //从node_modules里面抽取
              chunks:'initial', 
              minSize:0, //表示在压缩前的最小模块大小
              minChunks:2 //只要超过2次以上引用就抽离
            }
          }
        }

打包结果:

 

 7.懒加载

有时候我们会点击某个按钮再去加载对应的资源,也可以理解成是异步加载某个资源,如下代码:

let button = document.createElement('button')
button.innerHTML = 'hello'

//点击按钮加载资源
button.addEventListener('click',function(){ 
    //es6草案语法  其原理是jsonp实现动态加载文件
    import('./source.js').then(data=>{
        console.log(data)
    })
})
document.body.appendChild(button)

再点击按钮之后通过import加载了source.js文件,返回一个promise,就可拿到这个文件里的内容

 

 8.热更新

我们希望在页面发生了变化的时候只更新那一部分变化了的内容,而不是整个全部刷新。

webpack.config.js配置

devServer:{
      hot:true, //启用热更新
      port:3000,
      open:true,
      contentBase: './dist'
    },
plugins:[new webpack.HotModuleReplacementPlugin(), //热更新插件
        new webpack.NamedModulesPlugin() //告诉哪个模块更新了
    ]

index.js

import str from './source.js'
console.log(str)
if(module.hot) {
  module.hot.accept('./source.js',()=>{
    //import只能写在页面的顶端
    let str = require('./source.js')
    console.log(str.default)
  })
}

当source.js内容发生了变化就不会刷新整个页面了而是更新一部分

 

当然最好能搞懂热更新的原理 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2020-03-24 23:39  leahtao  阅读(194)  评论(0编辑  收藏  举报