玩转webpack(二)—— 进阶篇

1. 自动清理构建目录产物

每次在构建的时候不会清理目录,这会造成构建的输出目录的输出文件越来越多

  • 通过npm scripts清理构建目录
    在每次构建前先删除dist目录,可在package.json中的scripts配置:
rm -rf ./dist && webpack
或
rimraf ./dist && webpack

但是这种方法需要手动操作

  • 通过clean-webpack-plugin插件自动清理构建目录
    这个插件会在每次构建的时候删除output指定的输出目录
const  { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
	output: {
		filename: ....,
		path: __dirname + '/dist'       //clean-webpack-plugin插件会自动清除这个目录
	},
	plugins: [
		new CleanWebpackPlugin();
	]
}

⚠️为啥上面引入插件是 { CleanWebpackPlugin }
clean-webpack-plugin(https://github.com/johnagan/clean-webpack-plugin) 在5.29的时候发布了3.0版本,用法变了。


2. 自动补齐css3样式前缀

  • css3的属性为什么需要前缀?
    因为浏览器的标准并没有完全统一 。
浏览器内核css3前缀
Trident-ms
Geko-moz
Webkit-webkit
Presto-o
// 比如给一个元素设置border-radius属性
.box{
	-moz-border-radius: 10px;
	-webkit-border-radius: 10px;
	-o-border-radius: 10px;
	border-radius: 10px;
}

手动添加很麻烦

  • 通过使用autoprefixer插件自动补齐css3的前缀
    这是代码生成后再进行后缀处理
    autoprefixer需要配合postcss-loader使用

npm i postcss-loader autoprefixer -D

module.exports = {
	// ....
	 module: {
        rules: [
            {
                test: /\.less$/,
                use: [
                    'style-loader',
                    'css-loader',
                    {
                        loader: 'postcss-loader',
                        options: {
                            plugins:() => [
                                require('autoprefixer')({
                                    browsers: ['last 2 version', '> 1%', 'iOS 7']   //  兼容浏览器版本
                                })
                            ]
                        }
                    }
                ]
            }
        ]
    }
}

3. 移动端CSS的px转换成rem

页面适配问题

  • 以前通过css媒体查询实现响应式布局
    缺点:需要写多套适配样式代码
@media screen and (max-width: 980px) { .header {
width: 900px; }
}
@media screen and (max-width: 480px) {
.header {
height: 400px; }
}
@media screen and (max-width: 350px) {
.header {
height: 300px; }
}

rem是什么?
W3C对rem的定义: font-size of the root element
rem是相对单位
px是绝对单位
点击查看rem em px的区别 >>

  • 使用px2rem-loader将px转换成rem
  • 页面渲染时需要计算根元素的font-size的值
  • 可以借助手淘的lib-flexible库
  • https://github.com/amfe/lib-flexible
  • npm i px2rem-loader -D
  • npm i lib-flexible -S
  • html 的script需要引入安装的lib-flexible库的代码(下面会讲怎么将库资源内联近代码)
module.exports = {
 module: {
 	rules: [
		{
			test: /\.css$/,
			use: [
				'style-loader',
				'css-loader',
				{
					loader: 'px2rem-loader',
					options: {
						remUnit: 75,    // rem相对于px转换的倍数 1rem = 75px
						remPrecision: 8   // px转换为rem小数点的位数
					}
				}
			]
		}
	]
 }
}

4. 静态资源内联

资源内联的意义:

  • 代码层面:
    页面框架初始化脚本
    上报相关打点
    css内联避免页面闪动

  • 请求层面:
    减少HTTP网络请求数
    小图片或字体内联(url-loader)

一、HTML和JS的内联
都使用raw-loader
因为内联进来的代码可能存在一些ES6的属性,所以需要先使用babel-loader进行转换在内联进去

  • 内联HTML
<script>${require('raw-loader!babel-loader!./meta.html')}</script>
  • 内联JS(比如上述需要内联的lib-flexbile库)
<script>${require('raw-loader!babel-loader!../node_modules/lib-flexible')}</script>

二、CSS内联的两种方案

  • 借助style-loader加参数
module.exports = {
	// ....
	module: {
		rules: [
			{
				test: /\.css$/,
				use: [
					{
						loader: 'style-loader',
						options: {
							insertAt: 'top',    //样式插入到<head>标签内
							singleton: true   // 是否将所有的style标签合成一个
						}
					},
					'css-loader'
				]
			}
		]
	}
}
  • 使用html-inline-css-webpack-plugin插件
    npm i html-inline-css-webpack-plugin -D
    ⚠️使用这个插件内联css,那么就不会单独抽离css了,则mini-css-extract-plugin将失效
const HtmlInlineCssWebpackplugin = require('html-inline-css-webpack-plugin').default;
module.exports = {
	// ..
	plugins: [
		new HtmlInlineCssWebpackplugin()
	]
}

5. 多页面应用打包方案

每次页面跳转的时候,后台服务器都会返回一个新的html文档,这种类型的网站就是多页网站,也叫做多页应用

  • 多页应用的优势:
    每个页面之间是解藕的
    对SEO更加友好

  • 在webpack里如何打包多页面:

  1. 每个页面对应一个entry,一个html-webpack-plugin

这样的缺点:每次增加一个页面都需要更改webpack配置

  1. 动态获取entry和设置html-webpack-plugin数量(利用glob.sync)
    entry: glob.sync(path.join(__dirname, './src/*/*.js'))

npm i glob -D


6. 使用sourcemap

  • 作用: 通过source map可以定位到源代码(方便调试)
  • 开发环境默认开启,线上环境默认关闭

source map关键字:

  • eval: 使用eval包裹模块代码
  • source-map: 产生.map文件
  • cheap: 不包含列信息(比如报错时候会定位到多少行多少列,使用cheap就只能定位到多少行,无法定位到多少列)
  • inline-source-map: 将.map作为DataURI嵌入,不单独生成.map文件(将.map文件inline进了输出文件最后一行)
  • module:包含loader的sourcemap

使用:

module.exports = {
	devtool: 'eval'
}

如果不开启source map在带啊嘛中打断点无法定位到源代码,而是会定位到打包后到代码,不方便调试。


7. 提取公共资源

  • 基础库分离,

  • 比如:将react react-dom基础包通过cdn引入,不导入bundle中

  • 方法一:使用html-webpack-externals-plugin将基础包通过cdn引入,不打入bundle中

  • webpack4内置的一个功能非常大的插件代替了CommonsChunkPlugin插件

chunks参数说明:

  • async 异步引入的库进行分离(默认)
  • initial 同步引入的库进行分离
  • all 所有引入的库进行分离(推荐)

// 以下是默认参数值

module.exports = {
	optimization : {
		splitChunks : {
			chunks: 'async',
			minSize: 30000,   // 抽离的公共包最小的大小
			maxSize: 0,
			minChunks: 1,   // 公共文件最小使用次数(大于这个值才会提取成公共文件)
			maxAsyncRequests: 5,
			maxInitialRequests: 3,
			automaticNameDelimiter: '~',
			name: true,
			cacheGroups: {
				vendors: {
					test: /[\\/]node_modules[\\/]/,
					priority: -10
				}
			}
		}
	}
}

8. tree shaking(摇树优化)

(对模块代码静态分析)

  • 概念:一个模块可能有多个方法,只要其中某个方法使用到了,则整个文件都会被打到bundle里面去,tree shaking就是只把用到的方法打入bundle,没用到到方法会在uglify阶段被擦出掉。

  • 使用:webpack4默认支持,在.babelrc里面设置modules: false即可, 在production mode的情况下默认开启

  • 要求:必须是ES6的语法,CJS的方式不支持

  • 理解DCE(Dead Code Elimination) ->无用代码擦除
    无用代码举例:

  • 代码不会被执行,不可到达

  • 代码执行的结果不会被用到

  • 代码只会影响死变量(只读不写)

if(false) {
	console.log(这段代码永远不会被执行到);
}
  • tree shaking原理:
    • 1.利用 ES6模块的特点:
      • 只能作为模块顶层的语句出现
      • import 的模块只能是字符串常量
      • import binding是immutable的
    • 2.代码擦除:
      • uglify阶段无用代码擦除

9. Scope Hoisting使用和原理分析

  • 存在现象: 构建后的代码存在大量闭包代码
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值