前端面试之webpack和babel

webpack

  • webpack已是前端打包构建的不二选择
  • 每日必用,面试必考
  • 成熟的工具,重点在于配置和使用,原理并不高优(只在开发环境使用,线上不用)

讲解范围

  • 基本配置
  • 高级配置
  • 优化打包效率
  • 优化产出代码
  • 构建流程概述
  • babel

webpack面试题

  • 前端代码为何要进行构建和打包
  • module chunk bundle分别什么意思,有何区别
  • loader和plugin的区别
  • webpack如何实现懒加载
  • webpack常见性能优化
  • babel-runtime和babel-polyfill的区别

webpack基本配置

  • vue-cli create-react-app

  • 常用上述脚手架,而不会自己配置webpack?CLI工程师…

  • 则面试不会通过

  • 拆分配置和merge

拆分配置和merge
  • common - 公共配置
  • dev - development配置
  • prod - production配置

在development或者production模式中引入webpack-merge模块,将common配置merge进来

const webpackCommonConf = require('./webpack.common.js') // 引入公共模块文件
const { smart } = require('webpack-merge')
module.exports = smart(webpackCommonConf, {
	mode: 'development', 
	module: {
		rules: []
	},
	plugins: [
		new webpack.DefinePlugin({
			// window.ENV = 'development'
			ENV: JSON.stringify('development')
		})
	]
})
  • Path - 文件路径可单独配置文件夹

  • 本地代理配置,底层用到了http-proxy-middleware

    // 设置代理
    proxy: {
    	// 将本地/api/xxx代理到localhost: 3000/api/xxx
    	'/api': 'http://localhost: 3000',
    	// 将本地/api2/xxx代理到localhost: 3000/xxx
    	'/api2': {
    		target: 'http://localhost: 3000',
    		pathRewrite: {
    			'/api2': ''
    		}
    	}
    }
    
  • loader的执行顺序是从后往前

    rules: [
    	{
    		test: /\.css$/,
    		// loader的执行顺序是 从后往前
    		// postcss 浏览器兼容性写法 需要在postcss.config.js中引入autoprefixer
    		loader: ['style-loader', 'css-loader', 'postcss-loader']
    	}
    ]
    
  • 对图片的处理 dev和prod分开处理

    小于5kb的图片用base64格式产出,否则依旧沿用file-loader的形式,生成url链接,放在特定的img文件夹中

    rules: [
    	{
    		test: /\.(png|jpg|jpeg|gif)$/,
    		use: {
    			limit: 5*1024,
    			outputPath: '/img1/',
    		}
    	}
    ]
    
  • prod环境output使用contentHash

    output: {
    	filename: 'bundle.[contentHash:8].js',
    	path: distPath,
    }
    

webpack高级配置

  • 基本配置只能做demo,不能做线上项目

  • 面试考察基本配置,只是为了快速判断你是否用过webpack

  • 以下高级配置,也是通过面试的必要条件

  • 多入口

  • 抽离css文件(用MiniCssExtractPlugin),压缩css

  • 抽离公共代码和第三方模块

  • 懒加载

  • 处理jsx

  • 处理vue

module chunk bundle的区别

  • module - 各个源码文件,webpack中一切皆模块
  • chunk - 多模块合并成的,如entry import() splitChunk
  • bundle - 最终的输出文件

webpack性能优化

  • 大厂必考&社区热议话题
  • 优化打包构造速度 - 开发体验和效率
  • 优化产出代码 - 产品性能

webpack性能优化 - 构建速度

  • 优化babel-loader
  • IgnorePlugin
  • noParse 不去管哪些
  • happyPack 多进程打包工具
  • ParallelUglifyPlugin 多进程代码压缩js
  • 自动刷新
  • 热更新
  • DllPlugin
优化babel-loader
{
  	test: /\.js$/,
  	use: ['babel-loader?cacheDirectory'], // 开启缓存
  	include: path.resolve(__dirname, 'src'), // 明确范围,也可用排除范围exclude,二者选其一即可
    // exclude: path.resolve(__dirname, 'node_modules')
}
happyPack多进程打包
  • js单线程,开启多进程打包
  • 提高构建速度(特别是多核CPU)

关于开启多进程

  • 项目较大,打包较慢,开启多进程能提高速度
  • 项目较小,打包很快,开启多进程会降低速度(进程开销)
  • 按需使用
自动刷新
热更新
  • 自动刷新:整个网页全部刷新,速度较慢
  • 自动刷新:整个网页全部刷新,状态会丢失
  • 热更新:新代码生效,网页不刷新,状态不丢失
DllPlugin动态链接库插件
  • 前端框架如vue React,体积大,构建慢

  • 较稳定,不常升级版本

  • 同一个版本只构建一次即可,不用每次都重新构建

  • 打包

  • 引用

webpack优化构建速度(可用于生产环境)

  • 优化babel-loader
  • IgonrePlugin
  • noParse
  • happyPack
  • ParallelUglifyPlugin

webpack优化构建速度(不用于生产环境)

  • 自动刷新
  • 热更新
  • DllPlugin

webpack性能优化 - 产出代码

效果

  • 体积更小
  • 合理分包,不重复加载
  • 速度更快、内存使用更少

优化方式

  • 小图片base64编码 - 小于5kb或3kb的图片用base64格式产出
  • bundle 加 hash output中filename加contentHash: 8位数 目的是为了命中缓存
  • 懒加载 - import 原理同组件或路由异步加载
  • 提取公共代码 - 分两块 一个是第三方库 一个是项目中的公共代码 chunks;
  • IngorePlugin - moment库
  • 使用cdn加速 - 产出代码引用的是cdn的链接
  • 使用production模式
  • 使用Scope Hosting
使用production模式

优点

  • 自动开启压缩代码
  • vue react等会自动删掉调试代码(如开发环境的warning )
  • 启动Tree-Shaking 按需引入// ES6 Module才能让tree-shaking生效 用commonjs不生效
es6 Module和Commonjs区别
  • ES6 module静态引用,编译时引入
  • commonjs动态引用,执行时引入
  • 只有es6 module才能静态分析,实现tree-shaking
// commonjs动态引入
let apiList = require('../config/api.js');
if (isDev) {
    // 可以动态引入,执行时引入
  	apiList = require('../config/api_dev.js');
}


// es6 module
import apiList from '../config/api.js'
if (isDev) {
  	// 编译时报错,只能静态引入
    import apiList from '../config/api_dev.js'
}
scope hosting

效果

  • 代码体积更小
  • 创建函数作用域更少
  • 代码可读性更好
// hello.js
export default 'Hello 双越'

// main.js
import str from './hello.js'
console.log(str)

默认会打包成两个函数

开启scope hosting之后 会被打包成一个函数

[	
	(function(module, __webpack_exports__, __webpack_require__) {		
		var hello = ('Hello 双越');		
		console.log(hello);
	})
]

实现方式

通过ModuleConcatenationPlugin

cosnt ModuleConcatenationPlugin = require('webpack/lib/optimize/ModuleConcatenationPlugin')
module.exports = {	
	resolve: {		
// 针对 NPM 中的第三方模块优先采用jsnext:main中指向的ES6模块化语法的文件
		mainFields: ['jsnext:main', 'browser', 'main']	
	},	
	plugin: [		
		// scope hosting		
		new ModuleConcatenationPlugin(),	
	]
}

babel

  • 前端开发环境必备工具

  • 同webpack,需要了解基本的配置和使用

  • 面试考察概率不高,但要求必会

  • 环境搭建 & 基本配置

  • babel-polyfill

  • babel-runtime

babel环境搭建和基本配置
  • 环境搭建
  • .babelrc配置
  • presets和plugins (presets 预设了大部分plugins)
// .babelrc
{
	"presets": [		
		"@babel/preset-env",		
		// 按需引用		
		{			
			"useBuiltIns": "usage",			
			"corejs": 3 // 版本		
		}	
	],	
	"plugins": []
}
babel-polyfill是什么
  • 什么是Polyfill - 补丁/兼容 (判断原型链上是否有某个方法 没有的话用polyfill写法)
  • core.js 和 regenerator(标准库 集成了es6+的语法)
  • babel-polyfill 即两者的集合
  • babel7.4之后弃用babel-polyfill
  • 推荐直接使用core-js和regenerator
  • 但并不影响面试会考察它

Babel-polyfill按需引入

  • 文件较大
  • 只有一部分功能,无需全部引入
  • 配置按需引入

babel-polyfill的问题

  • 污染全局环境
  • 如果做一个独立的web系统,则无碍
  • 如果做一个第三方lib,则会有问题
babel-runtime
  • 不污染全局环境
  • 原理: 更名 如Promise 更名为 _Promise等 不污染全局环境

babel总结

  • babel只解析语法 如箭头函数; Promise、includes等API解析不了(语法是符合es5语法规范);
  • 要解析Promise等API,需要使用babel-polyfill(是对core-js和regenerator的包装,缺点是会污染全局环境,如果是第三方lib库需要配合babel-runtime使用,原理是重命名,只使用babel-runtime时,实例方法无法工作。如果不是第三方lib,可直接按需引入babel-polyfill; useBuiltIns取usage实现按需引入)
babel-runtime的优缺点

优点:

  • 不会污染全局变量
  • 多次使用只会打包一次
  • 依赖统一按需引入,无重复引入,无多余引入
  • 避免 babel 编译的工具函数在每个模块里重复出现,减小库和工具包的体积

缺点:

  • 不支持实例化方法,如 Array.includes()
  • 如果使用的API用的次数不是很多,那么transform-runtime 引入polyfill的包会比不是transform-runtime 时大

前端为何要进行打包和构建(使用webpack的优点)

代码方面

  • 体积更小,加载更快(tree-shaking 压缩 合并)

  • 编译高级语言或语法(ts es6+ 模块化 scss)

  • 兼容性和错误检查(polyfill postcss eslint)

开发流程(前端工程化)

  • 统一、高效的开发环境
  • 统一的构建流程和产出标准
  • 集成公司构建规范(提测、上线等)

module chunk bundle的区别

  • module - 各个源码文件,webpack中一切皆模块
  • chunk - 多模块合并而成,如entry import() splitChunk
  • bundle - 产出文件

loader和plugin的区别

  • loader 模块转换器 如less -> css
  • Plugin 扩展插件,如HtmlWebpackPlugin

常见loader和plugin有哪些

loader

  • babel-loader
  • url-loader
  • file-loader
  • scss-loader
  • css-loader
  • style-loader

plugin

  • html-webpack-plugin

  • dll-plugin

  • IgnorePlugin

  • ModuleConcatenationPlugin

babel和webpack的区别

  • babel - js新语法编译工具,不关心模块化

  • webpack - 打包构建工具,是多个loader和plugin的集合

如何产出一个lib

  • 参考dll
output: {
	library: "library", // 引入方式 script 标签
	libraryTarget: 'umd' // 引入方式 模块化 如es6 cmd amd
}

babel-polyfill 和 babel-runtime

  • Babel-polyfill会造成全局污染
  • babel-runtime不会造成全局污染
  • 产出第三方lib要用babel-runtime

webpack如何实现懒加载

  • import()
  • 结合vue react异步组件
  • 结合vue-router react-router异步加载路由

为何proxy不能被polyfill

  • 如class可以用function模拟
  • 如promise可以用callback来模拟
  • 但proxy的功能用Object.defineProperty无法模拟
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值