webpack面试题

一、在webpack如何配置解析ES6和React?

1、首先安装@babel/core@babel/preset-envbabel-loader@babel/preset-react

2、使用babel-loader,babel的配置文件是:.babelrc

{
	"presets":[
		"@babel/preset-env",//将es6转es5规则
        "@babel/preset-react"//解析react jsx
	]
}

3、在webpack.config.js中,与entry、output同级的地方写加一个module对象,如下配置

const path = require('path')
module.exports = {
	entry:{
		index:'./src/index.js',
		search:'./src/search.js'
	},
	output:{
		path:path.join(__dirname,'dist'),
		filename:'[name].js'//使用占位符
	},
	module:{
		rules:[
			{
				test:/\.js$/,
				use:'babel-loader'//使用babel-loader
			}
		]
	}
}
二、阐述一下webapck热更新以及热更新原理?

1、webapck热更新又称热替换(HotModuleReplacement),缩写HMR,在代码文件发生变化之后自动构建,使用新构建的模块代替旧模块,并自动刷新浏览器

2、热更新原理
在这里插入图片描述

webpack构建出来的bundle.js本身不具备热更新的能力,HotModulesReplacementPlugin的作用就是将HMR runtime注入到bundle.js,是的bundle.js可以和HMR server建立websocket的通信连接

启动阶段:①②AB

​ 文件系统经过webpack compiler进行编译,将编译好的文件传送给bundle server服务器,然后浏览器以服务的方式启动

修改代码文件:①②③④⑤

​ 本地开发时对文件进行修改后,仍然进过webpack compiler进行编译,将代码发送给HRM server,HMR server() 知道哪些模块或者源代码发生了改变,通过websocket通知HMR Runtime(客户端)哪些模块发生了变化,通常是以jsonp的数据进行传输,HRM Runtime会更新我们的代码

三、文件指纹是什么?如何用?

文件指纹是打包输出的文件名后缀,用作文件的版本管理,常用的有hashchunkhashcontenthash

hash:与整个项目的构建相关,只要项目文件有修改,整个项目构建的hash值就会改变

chunkhash:与webpack打包的chunk有关,不同的entry会生成不同的chunkhash值

contenthash:根据文件内容来定义hash,contenthash值随文件内容的改变而改变

js的文件指纹设置

设置js文件的output的filename,用chunkhash

const path = require('path')
module.exports = {
	entry: {
		index: './src/index.js',
		search:'./src/search.js'
	},
	output:{
		path:path.join(__dirname,'dist'),
		filename:'[name]_[chunkhash:8].js'//使用占位符+文件指纹
	}
}
css的文件指纹设置

因为css一般是使用style-loader将css样式注入到style标签中,再添加到html的head中,并没有独立的css文件,所以需要使用MiniCssExtractPlugin插件将css文件提取出一个独立文件,利用src的方法添加到head中。

安装mini-css-extract-plugin插件,这个插件不能和style-loader公用

const path = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
	entry: {
		index: './src/index.js',
		search:'./src/search.js'
	},
	output:{
		path:path.join(__dirname,'dist'),
		filename:'[name]_[chunkhash].js'//使用占位符
	},
	mode:'development',
	module:{
		rules:[
			{
				test:/.css$/,
				use:[
					new MiniCssExtractPlugin.loader,"css-loader"
				]
			},
			{
				test:/.less$/,
				use:[
					new MiniCssExtractPlugin.loader,"css-loader","less-loader"
				]
			}
		]
	}
}
图片的文件指纹设置

使用file-loader的options中的name,用hash

占位符名称含义
[ext]资源文件后缀
[name]文件名称
[path]文件的相对路径
[folder]文件所在的文件夹
[contenthash]文件的内容hash,默认是md5生成
[hash]文件的内容hash,默认是md5生成
[emoji]一个随机的指代文件内容的emoji
const path = require('path')
module.exports = {
	entry: {
		index: './src/index.js',
		search:'./src/search.js'
	},
	output:{
		path:path.join(__dirname,'dist'),
		filename:'[name]_[chunkhash:8].js'//使用占位符
	},
	mode:'development',
	module:{
		rules:[
			{
				test:/.(png|jpg|gif|txt|svg)$/,
				use:[
					{
						loader:"file-loader",
						options:{
							name:'img/[name]_[hash:8].[ext]'
						}
					}
				]
			}
		]
	}
}
四、代码压缩
html压缩

修改html-webpack-plugin,设置压缩参数

css压缩

使用optimize-css-assets-webpack-plugin,同时需要安装css预处理器cssnano

js压缩

内置了uglifyis-webpack-plugin,可以自己安装设置参数

五、关于css优化
补齐css3前缀

安装postcss-loader、autoprefixer插件

{
    test:/.less$/,
        use:[
            new MiniCssExtractPlugin.loader,"css-loader","less-loader",
     		{
                loader:'postcss-loader',
                options:{
                    plugins:() => [
                        require('autoprefixer')({
                            browsers:['last 2 version','>1%','ios 7']
                        })
                    ]
                }
            }
        ]
}
移动端css px自动转换为rem

安装px2rem-loader -D、lib-flexible -S (-S安装到依赖中)

{
    test:/.less$/,
        use:[
            new MiniCssExtractPlugin.loader,"css-loader","less-loader",
     		{
                loader:'postcss-loader',
                options:{
                    plugins:() => [
                        require('autoprefixer')({
                            browsers:['last 2 version','>1%','ios 7']
                        })
                    ]
                }
            },
            {
            	loader:'px2rem-loader',
            	options:{
            		remUnit:75, // 1rem = 75px,适合750的设计稿
            		remPrecesion:8 // px转换为rem的后面的小数点位数
            	}
            }
        ]
}
六、source map是什么?怎么用?

开发环境通过source map定位到源代码,生产环境应该关闭,因为会暴露业务逻辑,或者避免使用inline-、eval-

关键字描述
eval使用eval包裹模块代码
source map产生.map文件
cheap不包含列信息
inline将.map作为DataURL嵌入,不单独生成.map文件
module包含loader的source map
七、说一下webpack的构建过程?
初始化参数

从配置文件和shell语句读取和合并参数,得到最终打包参数

开始编译

用得到的参数初始化编译对象,加载所有的配置的插件,执行对象的run方法开始编译

确定入口

根据配置中的entry找出所有的入口文件

编译模块

从入口文件出发,调用所有配置的loader对模块进行翻译,再找出该模块依赖的模块,递归本步骤知道所有入口依赖的文件都经过了处理

完成模块编译

使用loader翻译完所有模块之后,得到了每个模块被翻译后的最终内容和他们之间的依赖关系

输出资源

根据入口和模块之间的依赖关系,组装成一个个包含多个模块的chunk,再把每个chunk转换成一个单独的文件加入到输出列表

输出完成

在确定好输出内容后,根据配置确定输出路径和文件名,把文件内容写到文件系统

简单来说

  • 初始化:启动构建命令,获取和合并配置参数,加载plugin,实例化compiler
  • 编译:从entry出发,针对每个module串行调用对应的loader去翻译文件,再递归编译该module依赖的module
  • 输出:将编译好的module组成成chunk,将chunk转换成文件,将文件输出到文件系统中
八、如何提高webpack构建速度?优化代码打包体积?
代码压缩

见第四点

图片压缩

使用image-webpack-plugin

基础库(基础包)分离

思路:将react、react-dom或者vue包通过cdn引入,不打入bundle中

方法:使用html-webpack-externals-plugin,或者SplitChunkPlugin

const HtmlWebpackExternalsPlugin = require('html-webpack-externals-plugin')
plugins:[
    new HtmlWebpackExternalsPlugin({
        externals:[
            {
                module:'react',
                entry:'xxx',//cdn的文件链接
                global:'React'
            },
            {
                module:'react-dom',
                entry:'xxx',//cdn的文件链接
                global:'ReactDom'
            }
        ]
    })
]
//与entry在同一级
optimization:{
    splitChunks:{
        commons:{
            test:/(react|react-dom)/,
            name:'vendors',
            chunks:'all'
        }
    }
}
公共脚本代码分离

webpack4.0内置的SplitChunksPlugin代替CommonChunkPlugin

//与entry在同一级
optimization:{
    splitChunks:{
        minSize:0,
        cacheGroups:{
            commons:{
                name:'commons',
                chunks:'all',
                minChunks:2
            }
        }
    }
}
Tree shaking(摇树优化)-删除无用代码

将没有用的代码删除掉,比如

  • 代码不会被执行,不可达到
  • 代码执行的结果不会被用到
  • 代码只会影响死变量(只读不写)

利用ES6模块的特点:

  • 只能作为模块顶层的语句出现
  • import的模块只能是字符串常量
  • import binding是immutable的

代码擦除:uglify阶段删除无用代码

scope hoisting

构建后的代码会存在大量的闭包,造成体积增大,运行代码时创建的函数作用域变多,内存开销大。scope hoisting将所有的模块代码按照引用顺序放在一个函数作用域里,然后适当的重命名一些变量防止变量名冲突。

九、说一说loader和plugin的区别

loader在moudle.rules中配置,类型为数组。loader本质上是一个函数,该函数对接收到的内容进行转换,返回转回的结果。因为webapck只认识js,所以loader成了翻译官,对其他类型的资源进行转译的预处理工作。

plugin是plugins中配置,类型为数组,每一个都是plugin的实例。plugin本质上是插件基于事件流框架tapable, 在于解决 loader无法实现的其他事,可以扩展webpack的功能,执行范围更广的任务,从打包优化和压缩一直到重新定义环境中的变量。

十、对 webpack 的了解

webpack 是一个javascript 应用程序的静态模块打包器;将项目作为一个整体,通过一个入口文件,从这个文件开始递归构建一个依赖关系图,包括应用程序中所需要的各个模块,然后将所有这些模块打包成一个或者多个bundle

核心概念

  1. entry :入口文件,指示 webpack 应该使用哪一个模块,来作为构建项目内部依赖图的开始,可指定一个或多个入口文件
  2. output : output 属性指示 webpack 在哪里输出它所创建的bundle,以及如何命名这些文件,默认是./dist
  3. loader :loader用来处理非 javascript 文件,因为 webpack本身只理解 javascript
  4. plugins :loader 用来转换某些类型的模块,而插件可以用于执行范围更广的任务,任务包括打包优化压缩代码到重新定义环境中的变量;功能很强大,可以用来执行及其强大的任务
  5. mode :模式,可选择development/production,可根据模式启用相应模式下的 webpack 内置优化
十一、webpack、grunt和gulp的不同

三者都是前端构建工具

grunt和gulp都是基于任务和流的。找到一个或一类文件,对其做一系列链式操作,更新流上的数据,整条链式操作构成了一个任务,多个任务就构成了整个web的构建流程

webpack是基于入口的。webpack会自动地递归解析入口所需要的加载的所有资源文件,然后用不同的 loader 来处理不同的文件,用plugin来扩展webpack的功能

webpack与前者最大的不同是支持代码分割、模块化、全局分析

十二、常见loader
名称描述
babel-loader使用babel将ES6转换为ES5
css-loader支持.css文件的加载和解析
style-loader将css代码加入style标签再注入html文件的头部
less-loader将.less文件转换为css
sass-loader将.sass文件转换为css
ts-loader将typeScript转换为javascript
json-loader加载json文件
file-loader将文件输出到一个文件夹中,在代码中通过url去引用
url-loader与file-loader相似,有一个阈值的区别,小于阈值返回base64,大于阈值交给file-loader处理
postcss-loader扩展css语法,配置autoprefixer插件自动补齐不同浏览器的css3前缀
eslint-loader、tslint-loader通过eslint、tslint检查js、ts代码
vue-loader加载vue.js单文件组件
cache-loader可以在一些性能开销大的loader之前添加,目的是将结果缓存到磁盘
raw-loader将文件以字符串的形式引入
十三、介绍常见的plugin
名称描述
CommonsChunkPlugin将chunks相同的模块代码提取成公共js
CleanWebpackPlugin在构建之前先清理dist文件夹,清除无用的资源
MiniCssExtractPlugin将css从bundle文件里提取成一个独立的css文件,替代ExtractTextWebpackPlugin
CopyWebpackPlugin将文件或者文件夹拷贝到构建的输出目录
HtmlWebpackPlugin自动往index.html中注入打包生成的xxx.bundle.js文件,生成一个全新的html文件
UglifysWebpackPlugin使用uglify-js压缩 JavaScript
ZipwebpackPlugin将打包的出的资源生成一个zip包
DefinePlugin允许在编译时(compile time)配置的全局常量
HotMoudleReplacementPlugin启动热替换模块,主要用于本地启动
十四、本地开发是怎么解决跨域的
  1. 使用webpack-dev-server插件

  2. 配置webpack.config.js

    var WebpackDevServer = require("webpack-dev-server")
    module.exports = {
        ...
    	devServer:{
    		port:'8080',
    		proxy:{
    			'/api':{
    				target:'http:127.0.0.1',
    				changeOrigin: true,
    				pathRewrite:{
    					'^/api':''
    				}
    			}
    		}
    	}
    }
    
十五、是否写过loader和plugin,描述一下编写思路

loader:编写loader时要遵循单一原则,每个loader只做一种转义工作。每个loader拿到的是源文件内容(source),可以通过返回值的方式将处理后的内容输出,也可以调用this.callback()方法;还可通过this.async()生成一个 callback 函数,再用这个callback将处理后的内容输出出去

plugin:相对loader来说比较灵活。webpack 在运行的生命周期中会广播出许多事件,plugin可以监听这些事件,在合适的时机通过webpack 提供的api 改变输出结果

十六、怎么配置单页应用和多页应用

单页应用可以理解为webpack的标准模式,直接在entry中指定单页应用的入口即可

多页应用可使用webpack的AutoWebPlugin来完成简单的自动话构建,前提是项目的目录结构要遵守预设的规范

十七、什么是bundle、chunk、module

bundle:是webpack打包出来的文件

chunk:是webpack在进行模块的依赖分析时分割出来的代码块

module是开发中的单个模块

参考链接

「吐血整理」再来一打Webpack面试题

webpack中文文档

面试相关

后续会继续更新~~~

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值