webpack

241 阅读2分钟

plugins插件介绍:

plugins是用来拓展webpack功能的,这些功能会在整个构建过程中生效,执行相关任务,loaders和plugins常常被弄混,但是他们其实是完全不同的东西,loaders是对于某一类文件的处理,因为webpack只认识js文件,要打包其他文件就要用到loader,是在打包构建的过程中用来处理源文件的(jsx,scss,less)一次处理一个,plugins并不直接操作单个文件,它直接对整个构建过程起作用

使用方法:

要使用某个插件,需要通过npm安装,然后在webpack.config.js中的pluins模块中添加该插件的一个实例,(plugins是一个数组,new一个插件即可)

插件:

webpack.DefinePlugin----在打包阶段定义全集变量
webpack.HashedModuleldsPlugin----保持moudle.id稳定
webpack.NoEmitOnErrorsPlugin----屏蔽错误
webpack.ProvidePlugin--提供库
copy-webpack-plugin-可以帮助拷贝内容

案例:

在业务代码中获取全局变量:

webpack.config.js文件中 plugin模块
plugins:[
    new webpack.DefinePlugin({
        'process.env':env,
        'name':'小李'
    })
    
    new webpack.ProvidePlugin({
        "$":'jquery'
    })
]

为什么业务打包要带hash?? hash和缓存有关,为了标识代码是否被更改

页面中使用:

webpack.ProvidePlugin中的jq:
helloworld.vue:
mounted(){
    $.ajax({
        
    })
}
优点就是不用在每个vue文件中再次引用$,可以帮助提供全局的插件,虽然可以在main.js中引入全局但是会污染vue,
copy-webpack-plugin-可以帮助拷贝内容
比如在在项目中引入了100张图片,而你只使用了20张,打包的时候剩余的80张是不会打包进dist文件夹的,如果想打包进入就可以使用这个插件
webpack.NoEmitOnErrorsPlugin----屏蔽错误
在开发阶段帮助屏蔽一些错误,比如在打包的时候发生报错现象,打包会立马停止,加上这个插件后,会先打包完毕,

webpack3和webpack4的不同:

webpack4理念:0配置打包

webpack3在webpack配置中是没有mode这个配置的,webpack3对代码压缩必须要在plugins中配置

plugins:[
    new webpack.optimize
]

webpack4中打包压缩: 直接在webpack.config.js中的mode中配置:

module.exports={
    mode:"production"
}

webpack打包优化:(解决打包速度慢的问题)

Dll优化(提前打包第三方模块)

webpack的打包时间是由-模块,操作决定的;

dll打包原理:

我们改代码的时候一般改的就是业务代码,往往不会去修改第三方模块,所以打包的时候能不能忽略第三方模块呢???只处理业务代码,这样打包就提高速度了,所以打包之前能不能先处理好第三方模块,在真正打包的时候就不要再去动第三方模块!!!这就是dll原理,提前处理第三方模块,真正打包的时候不去动第三方模块

dll实现:

新建一个webpack.dll.config.js

const webpack = require('webpack');
module.exports = {
    entry:{
        vendor:['jquery','loadsh']------这里只提前要处理的引入第三方模块
    },
    output:{
        path:__dirname:"/dll",
        filename:"[name].dll.js",
        library:'[name]_library'
    },
    plugins:[
        new webpack.DllPlugin({
            path:__dirname+"/dll/[name]-manifest.json",
            name:'[name]_library'
        })
    ]
}

然后在webpack.config.js中去通知webpack已经提前打包好第三方模块了: 在webpack.config.js中:

plugins:[
     new webpack.DllReferencePlugin({
        manifest:require('./dll/vendor-manifest.json')
    })
]

执行: 先执行 webpack --config webpack.dll.congif.js 再执行 webapcl

Happypack优化(把单线程打包改为多线程打包):

Happypack原理:

js是单线程的,node有开多线程能力,打包是在node环境下进行的,webpack也是node写的(利用node能力开多个工作进程一起来打包,把单线程打包改为多线程打包)代替loader去打包

使用:

先安装下载 然后在webpack.config.js中

先在webpack.config.js中引入HappyPack;

const HappyPack = require('happyPack');
const os = require('os');//node内置模块-提供电脑的信息
const happyThreadPool = HappyPack.ThreadPool({size:os.cpus().length});//线程池-根据电脑cpu去确定

module.exports={
    mode:"development",
    entry:{
        app:'./app.js'
    },
    output:{
        filename:[name].js
    },
    module:{
        rules:[
            {
               test:/\.js$/,
               use:[
                    {
                        //loader:'babel-loader'  
                        loader:'happypack/loader?id=happybabel'   
                    }
               ]
            },
            {
               test:/\.css$/,
               use:'happypack/loader?id=happycss' 
            }
        ]
    },
    plugins:[
        new HappyPack({
            id:"happybabel",
            loaders:['babel-loader?cacheDirectory=true'],
            threadPool:happyThreadPool
        }),
        new HappyPack({
            id:"happycss",
            loaders:['css-loader?cacheDirectory=true'],
            threadPool:happyThreadPool
        }),
    ]
}

happypack不一定会加速,甚至会拖慢速度,不建议把所有的loader都用happypack替换 原因:打包快慢是由模块数量和操作决定的,也包括优化操作,一般不建议把css文件替换,一般.vue比较多

解决方案归纳:

  • 如果是要对模块内容进行处理----Loader是第一解决方案
  • 如果要增加一些特殊的功能--可以自定义增加插件
  • 项目上的打包简化,可变性配置--通过编写相应的操作函数

骚操作1:

目的:把打包后的js文件中的bind全部替换为on,源文件不会改变

新建myloader.js


module.exports= function(context){
    console.log(context);
    return context.replace('bind','on');
}

在webpack.congif.js中


module.exports={
    mode:"development",
    entry:{
        app:'./app.js'
    },
    output:{
        filename:[name].js
    },
    module:{
        rules:[
            {
               test:/\.js$/,
               use:[
                    {
                        loader:'./myloader.js'
                    }
               ]
            }
        ]
    },
    plugins:[
     
    ]
}

骚操作2:自定义plugin插件

目的: 把打包后的请求地址'./static/img/'替换为'www.xx.com'

新建文件夹myplugin; 再文件夹新建index.js

module.exports=a;
function a(){
    
}
a.prototype.apply=function(compiler){
    //插件原理:所有插件都是基于一个生命周期的监听的
    //emit,done等周期
    //我在done周期上注册了一个插件changeStatic
    //hooks获取webpack生命周期
    compiler.hooks.done.tap('changeStatic',function(compilation){
    //compilation打包结果  
    //compilation.toJson().assets为最终打包自愿的结果['./app.js','./index.html']
        let context = compiler.options.context;//获取当前地址
        let publicpath = path.resolve(context,'dist');//拿到dist目录
        compilation.toJson().assets.forEach((ast)=>{
            const filepath = path.resolve(publicpath,ast.name);
            fs.readFile(filepath,function(err,file){
                var newcontext = file.toString().replace('./static',www.xx.com);
                fs.writeFile(filepath,newcontext);
            })
        })
    });
}
在webpack.config.js中
先引入myplugin
const myplugin = require(./myplugin);
module.exports={
    mode:"development",
    entry:{
        app:'./app.js'
    },
    output:{
        filename:[name].js
    },
    module:{
        rules:[
            
        ]
    },
    plugins:[
        new myplugin(),
    ]
}