webpack打包工具

1.Webpack基本概念与配置
基本概念:
webpack是一个前端模块化的方案,更侧重于模块打包,我们可以把开发中的所有资源(图片、js文件、css文件等)都看成模块,通过loader和plugin对资源进行处理,打包成符合生产环境部署的前端资源。
基本配置:
entry(项目入口)[entri]
output(出口文件,告诉webpack在哪里输出文件以及对文件的命名)
module(模块的处理)
主要就是用到了loader,它的第一个参数就是test,主要用于识别文件类型,第二个参数就是使用相关的loader对文件进行处理。
plugin插件
主要用到了htmlwebpackplugin插件,可以创建html入口文件
2. loader与plugin原理与实现
1.plugin:

var htmlWebpackPlugin=require(‘html-webpack-plugin’)//引入插件
module.exports={
    plugins:[
        new htmlWebpackPlugin()
    ]
}
new webpack.BannerPlugin("最终版权归aaa所有")
new UglifyjsWebpackPlugin()//压缩文件uglifyjswebpackplugin

运行一下生成html文件,但是跟我们自定义的html文件没有任何的联系,能够得到如下结果:
在这里插入图片描述
可以发现生成的js的文件名自动进行了更正变成了[name]-[hash]的格式,这样子就不需要手动的进行更改。
如何跟自定义的html关联起来呢?

var htmlWebpackPlugin=require(‘html-webpack-plugin’)//引入插件
module.exports={
    plugins:[
        new htmlWebpackPlugin({
           filename:'index-[hash].html',
           template:'index.html',//自定义的html
           inject:'head',//将脚本放在头部
           title:'webpack is good',//参数传值
           date:new Date(),//参数传值
           minify:{
              removeCmoments:true,//删除注释打开
              collapseWhitespace:true  //删除空格加上
              
           }//对当前的html文件进行压缩collapse
        })
    ]
}
接收参数在html文件中
在自定义的html文件中
<title><%=htmlWebpackPlugin.options.title %></title>
<body><%=htmlWebpackPlugin.options.date %>/body>

关联起来了。
当需要生成多个html文件时,可以使用如下:
在这里插入图片描述
但是上面这样子是有问题的,不管是哪个html文件最后生成的都是一模一样的,但是基本上生成的肯定是不一样的,比如说a.html只需要加载main.js,而b.html只需要加载b.js,不需要其他的,就要加入chunks属性。
代码如下:

plugins:[
   new htmlWebpackPlugin({
      filename:"a.html",
      template:"index.html",
      inject:false,
      title:"this is a.html",
      chunks:['main','a']
   })
]

2.loader
1.babel-loader:

module.exports={
    entry:"./src/app.js",
    output:{
     path:'dist',
     filename:'js/[name].bundle.js'
    },
    module:{
      loaders:[
        {
          test:/\.js$/,
          loader:'babel',
          query:{//参数
             presets:['latest']//配置,每年es的语法都在更新转换,所以可以使用latest(这个的话就所有都包括了es2017,es2016,es2015)
          }
        }
      ]
    }
}

2.css-loader,style-loader
css-loader:加载CSS文件
style-loader:将样式添加到dom中生效

module:{
   loaders:[
   {test:/\.css$/,
    loader:'style-loader!css-loader!postcss-loader'
   }
  ]
},
postcss:[
   require('autoprefixer')({
      broswers:['last 5 versions']//通过加入这句话能够解决兼容性问题,会在css样式中加入前缀-ms-box之类的。
   })
]
但是在css文件中通过@import ./a.css引入进来的css文件是不会经过postcss的,怎么办呢?
loader:'style-loader!css-loader?importLoaders=1!postcss-loader'
因为在后面只跟了一个postcss-loader,所以importLoaders=1

2.less-loader,sass-loader

loaders:[
   {test:/\.less$/,
    loader:'style-loader!css-loader!postcss-loader!less-loader'
   },
   {test:/\.sass$/,
    loader:'style-loader!css-loader!postcss-loader!sass-loader'
   }  ]

3.处理图片以及其他文件
图片文件:
file-loader

//file-loader
{
 test:/\.(png|jpg|gif|svg)$/i,
 loader:"file-loader"
 query:{
    name:'assets/[name]-[hash:5].[ext]'//图片最后打包成功以后所放置的位置。
 }
}

url-loader
url-loader和file-loader很类似,都是可以处理图片等文件,但是url-loader多了一个参数设置,该参数为limit,当你实际的文件大小大于所设置的limit大小的时候,会采用file-loader,当你实际的文件大小小于所设置的limit大小的时候,它就会直接转为base64文件,变成一段编码,而不是url。

{
 test:/\.(png|jpg|gif|svg)$/i,
 loader:"url-loader"
 query:{
    limit:20000,
    name:'assets/[name]-[hash:5].[ext]'//图片最后打包成功以后所放置的位置。
 }
}

url-loader和file-loader各有各的优势,当你用http请求载入进来的图片时,可以享受到浏览器的缓存,当你用base64的时候,增加代码的体积。基本上会使用image-webpack-loader进行图片的压缩。
image-webpack-loader//图片的压缩

{
 test:/\.(png|jpg|gif|svg)$/i,
 loaders:['url-loader?limit=20000&name=assets/[name]-[hash:5].[ext]','image-webpack']
 }

3. Webpack的模块热替换及实现
//搭建本地服务器
//webpack提供了一个可选的本地开发服务器,这个本地服务器基于node.js搭建,内部使用express框架,可以实现我们想要的让浏览器自动刷新显示我们修改后的结果
//不过它是一个单独的模块,在webpack中使用之前需要先安装它
//npm install --save-dev webpack-dev-server@2.9.1
//devserver也是作为webpack中的一个选项,选项本身可以设置如下属性:
//contentBase:为哪一个文件夹提供本地服务,默认是根文件夹,我们这里要填写./dist
//port:端口号,默认8080
//inline://页面实时刷新
//historyApiFallback:在SPA页面中,依赖HTML5的history模式

webpack的模块热替换的技术可在不刷新整个页面的情况下做到超灵敏的实时预览。原理是当一个源码发生变化的时候,只重新编译发生变化的模块,再用新输出的模块替换掉浏览器中对应的老模块。
模块热替换技术的优势有:
(1).实时预览反应更快,等待时间更短。
(2).不刷新浏览器能保留当前网页的运行状态。
模块热替换的实现:
1.模块热替换的原理和自动刷新原理类似,都需要往要开发的网页中注入一个代理客户端用于连接DevServer和网页, 不同在于模块热替换独特的模块替换机制。

const HotModuleReplacementPlugin = require('webpack/lib/HotModuleReplacementPlugin');
module.exports = {
  entry:{
    // 为每个入口都注入代理客户端
    main:['webpack-dev-server/client?http://localhost:8080/', 'webpack/hot/dev-server','./src/main.js'],
  },
  plugins: [
    // 该插件的作用就是实现模块热替换,实际上当启动时带上 `--hot` 参数,会注入该插件,生成 .hot-update.json 文件。
    new HotModuleReplacementPlugin(),
  ],
  devServer:{
    // 告诉 DevServer 要开启模块热替换模式
    hot: true,      
  }  
};

当修改源码main.css文件后,会产生一个补丁文件0.ea11a51f97f2b52bca7d.hot-update.js,同时在浏览器开发工具中也能够看到请求这个补丁的抓包:
在这里插入图片描述
在这里插入图片描述
当你编辑main.js文件时,你会发现整个网页被刷新了,为什么会这样呢?
是因为如果事件一直往上抛到最外层都没有文件接受它,就会直接刷新网页。二如果是main.js里面的子模块发生变化的时候,就不会直接刷新网页,因为有mian.js接受它了。
优化模块热替换:
其中的Updated modules: 68是指ID为68的模块被替换了,这对开发者来说很不友好,因为开发者不知道ID和模块之间的对应关系,最好是把替换了的模块的名称输出出来。Webpack内置的NamedModulesPlugin插件可以解决该问题,修改Webpack配置文件接入该插件:

devServer:{
    contentBase: './dist',
    inline:true
  }

4. Webpack的优化问题
1.压缩代码。
压缩js文件
const uglifyjsWebpackPlugin=require(“uglifyjs-webpack-plugin”)
new UglifyjsWebpackPlugin()
webpack自带的webpack.optimize.UglifyJsPlugin()来进行压缩。
plugins:[new webpack.optimize.UglifyJsPlugin()]//压缩js文件
压缩css文件
首先需要将css文件单独打包
所以要先安装 extract-text-webpack-plugin@3.0.2。
因为一般来说进行打包的时候会把js和css打包在一个js文件里面,这样子不是很好,所以就要把css给抽离出来单独成为一个css文件

安装压缩 css 文件的插件 optimize-css-assets-webpack-plugin@3.2.0
在 webpack.config.js 中配置这两个插件.

const ExtractTextPlugin = require('extract-text-webpack-plugin') // css文件单独打包
const OptimizeCssplugin = require('optimize-css-assets-webpack-plugin') // 压缩css文件

将css文件单独打包

{
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: 'style-loader',//loader应用于当css没有被提取
          use: 'css-loader'//loader被用于将资源转换成一个css导出模块
        })
      },
      
plugins:[ new ExtractTextPlugin('css/style.css')//指定单独打包的css文件存储路径和名字 
new OptimizeCssplugin()//压缩css文件
]

压缩图片文件
image-webpack-loader

{
  test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
  use:[
    {
    loader: 'url-loader',
    options: {
      limit: 10000,
      name: utils.assetsPath('img/[name].[hash:7].[ext]')
      }
    },
    {
      //当图片很大的时候,可以选择使用这个进行压缩,压缩图片要在file-loader之后使用
      loader: 'image-webpack-loader',// 压缩图片
      options: {
        bypassOnDebug: true,//加快初始化
      }
    }
  ]
}

2.利用CDN加速,将引用的静态资源修改为CDN上对应的路径,可以利用webpack对于output参数和loader的publicpath参数来修改资源路径。
3.删除死代码(tree shaking),css需要使用Purify-CSS

const glob=require("glob");
const PurifyCssWebpack=require("purifycss-webpack");
plugins:[
 new PurifyCssWebpack({
     paths:glob.sync(path.join(_dirname,'src/*.html'))
  })
]

4.提取公共代码。
多页应用一般会重复使用部分公共代码,这样每次加载单页的时候,就会重复去加载这些公共代码,会造成以下问题:
(1)相同资源重复被加载,浪费用户流量,增加服务器成本。
(2)每个页面需要加载的资源太大,导致网页首屏加载缓慢,影响用户体验。
如何抽取公共代码?
在这里插入图片描述
如上图,index.js和other.js都依赖了a .js和b.js,那么只需要将a.js和b.js抽离出来并打包成common.js,然后让index.js和other.js直接引用common.js即可。
webpack.config.js配置如下:
在这里插入图片描述
这样就能够在一开始就将大小小于0字节的,并且使用2次以上的代码抽离出来。index.js和other.js都引用了抽离出来的公共代码common.js。
如何抽离第三方库?
假设在上面的基础上,index.js和other.js都引用了jquery库,那么这样来配置抽离第三库
在这里插入图片描述
代码从上到下执行,会先执行common,然后执行vendor,而在执行common的时候,就把jquery抽离出来打包到跟a.js和b.js里面去了,后面的vendor就没有什么效果了。这并不是个好方案,我们最好是能够将库单独抽离出来,于是,可以这么操作:在vendor添加权重属性:priority,将权重提高,使得先去抽离第三方库,再去抽离a.js和b.js。
5.如果一个页面有多个入口,怎么配
可以在webpack的基本配置文件里面:

  module.exports={
     entry:{
          main:"./src/script/main.js",
          a:"./src/script/a.js"
      },
      output:{
          path:'./dist',//本地路径
          filename:'js/[name]-[hash].js',//[name]表示的entry中的main或a,而[hash]表示的哈希值,确保文件名的唯一性。
          publicPath:'http://cdn.com/'//上线需求
      }
  }

6.打包速度慢?
babel-loader是非常耗时的语法转换,那么如何进行优化呢?

module.exports={
    module:{
      loaders:[
        {test:/\.js$/,
         loader:'babel',
         exclude:'./node_modules/',//这里文件夹里面的就不要再语法转换了,减省时间。
         include:'./src/',//指定一个范围,就是只打包这个路径下面的来提升速度
         query:{
           presets:['latest']
         }
        }
      ]
    }
}

7.loader 和plugin不同
loader:使webpack拥有加载和解析非js的能力。
loader:主要用于转换某些类型的模块,它是一个转换器
plugin:plugin也是为了扩展webpack的功能,它的功能很多,比如说从打包优化和压缩。
8.webpack构建流程

  1. 确定入口,通过entry找到入口文件
  2. 编译模块,从入口文件出发,调用所有配置的loader对模块进行解析翻译,在找到该模块依赖的模块进行处理。
  3. 完成模块编译,得到每个模块被翻译之后的最终的内容和依赖关系。
  4. 输出资源,根据入口和模块之间的依赖关系,组装成一个个包含多个模块的chunk,在把每个chunk转换成一个单独的文件加载到输出列表。
  5. 输出完成,确定输出的路径和文件名,把内容写到文件系统中。
    9.什么是bundle,什么是chunk,什么是module?
    bundle:有webpack打包出来的文件。
    chunk:webpack在进行模块的依赖分析的时候,代码分割出来的代码块。
    module:开发中的单个模块。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值