目录
- 一、GIT
- 1.简述 Git 是什么,它有什么作用
- 2.请解释工作区、暂存区和本地仓库的概念
- 3.如何初始化一个新的 Git 仓库
- 4.如何将工作区的修改添加到暂存区,又如何将暂存区的内容提交到本地仓库
- 5.如何查看当前仓库的状态
- 6.解释 Git 分支的概念,以及如何创建和切换分支
- 7.如何将一个分支的修改合并到另一个分支
- 8. 如何查看提交历史记录
- 9.如何撤销工作区的修改和暂存区的修改
- 10.解释 Git 的远程仓库和本地仓库的关系,以及如何与远程仓库进行交互
- 11.如何进行 Git 的回滚操作,有哪些方式
- 12.在多人协作开发中,如何避免代码冲突
- 13.如何对 Git 仓库进行清理,删除不必要的文件和分支
- 14.简述 Git 钩子(Hooks)的作用和使用场景
- 二、webpack
- 1、webpack是什么
- 2、webpack五个核心概念
- 3、Loader 和插件的区别是什么
- 4、webpack.config.js作用
- 5、生成环境的部署
- 6、如何使用 Webpack 处理 CSS 文件以及CSS兼容性处理
- 7、如何压缩css
- 8、js语法检查怎么配置
- 9、js兼容性处理
- 10、js的压缩
- 11、html的压缩
- 12、如何使用 Webpack 优化生产环境的构建
- 13、Webpack 热更新(Hot Module Replacement,HMR)的原理是什么,如何配置
- 16、简述 Webpack 的构建流程
- 17、webpack如何找到依赖关系的
- 18、webpack如何配置
- 19.解释 Webpack 的代码分割(Code Splitting)及其实现方式
- 20.如何使用 Webpack 进行图片处理
- 21.如何监控 Webpack 的构建性能,有哪些优化策略
- 22.在微前端架构中,Webpack 可以发挥什么作用
- 23.如何使用 Webpack 处理 TypeScript 文件
- 24.postcss-loader是什么作用,style-loader,css-loader,less-loader分别做了哪些事情
- 25.用过哪些plugin,举例说明,plugin的内部实现是?
- 26webpack chunk和bundle的区别是?
- 三、NPM
一、GIT
1.简述 Git 是什么,它有什么作用
Git 是一个开源的分布式版本控制系统,常用于软件开发过程中的代码管理。它的主要作用包括:记录代码的修改历史,方便开发者追溯和恢复到任意版本;支持多人协作开发,允许多个开发者同时对项目进行修改并合并代码;可以创建分支,实现并行开发不同的功能或修复不同的问题。
2.请解释工作区、暂存区和本地仓库的概念
工作区:是你在本地计算机中实际进行文件编辑的目录,也就是你能看到和操作的项目文件所在的地方。
暂存区:也叫索引,是一个中间区域,用于临时保存你所做的修改。你可以选择将工作区中部分或全部的修改添加到暂存区。
本地仓库:是存储在你本地计算机上的完整版本库,包含了项目的所有历史提交记录。暂存区的内容可以被提交到本地仓库。
3.如何初始化一个新的 Git 仓库
在项目根目录下,打开终端并执行命令 git init,这样就会在该目录下创建一个新的 Git 仓库,同时会生成一个名为 .git 的隐藏目录,用于存储 Git 的相关信息。
4.如何将工作区的修改添加到暂存区,又如何将暂存区的内容提交到本地仓库
将工作区的修改添加到暂存区,使用命令 git add <文件名> 来添加指定文件,若要添加所有修改的文件,可使用 git add .。
将暂存区的内容提交到本地仓库,使用命令 git commit -m “提交说明”,其中 -m 后面跟着本次提交的简要描述。
5.如何查看当前仓库的状态
使用 git status 命令可以查看当前工作区和暂存区的状态,了解哪些文件被修改、哪些文件已添加到暂存区、哪些文件是新增的等信息。
6.解释 Git 分支的概念,以及如何创建和切换分支
Git 分支是指向某个提交对象的可变指针,它允许你在不影响主分支的情况下进行独立的开发工作。
创建分支使用命令 git branch <分支名>。
切换分支使用命令 git checkout <分支名>。也可以使用 git checkout -b <分支名> 来创建并切换到新分支。
7.如何将一个分支的修改合并到另一个分支
假设要将 feature 分支的修改合并到 master 分支,操作步骤如下:
首先切换到目标分支 master,使用 git checkout master。
然后执行合并操作,使用 git merge feature。
如果合并分支时出现冲突,应该如何解决
当合并分支出现冲突时,Git 会在有冲突的文件中标记出冲突的部分。你需要手动打开这些文件,编辑解决冲突。通常冲突部分会以类似下面的形式呈现:
<<<<<<< HEAD
这是当前分支(如master)的内容
=======
这是要合并进来的分支(如feature)的内容
>>>>>>> feature
你需要根据实际情况选择保留哪部分内容,或者对两部分内容进行整合。解决完冲突后,使用 git add <文件名> 将解决冲突后的文件添加到暂存区,再使用 git commit 完成合并提交。
8. 如何查看提交历史记录
使用 git log 命令可以查看详细的提交历史,包括提交的哈希值、作者、提交时间和提交说明等信息。
若希望以简洁的格式查看提交历史,可以使用 git log --oneline。
9.如何撤销工作区的修改和暂存区的修改
撤销工作区的修改,使用 git checkout – <文件名>,这样会将文件恢复到上一次提交时的状态。
撤销暂存区的修改,使用 git reset HEAD <文件名>,该操作会将文件从暂存区移除,但工作区的修改会保留。
10.解释 Git 的远程仓库和本地仓库的关系,以及如何与远程仓库进行交互
远程仓库是存储在远程服务器上的 Git 仓库,本地仓库则是你在本地计算机上的仓库。两者通过网络进行交互,方便团队成员之间共享代码。
与远程仓库进行交互的常用操作包括:
git clone <远程仓库地址>:将远程仓库克隆到本地。
git remote add <远程仓库名> <远程仓库地址>:将本地仓库与远程仓库关联起来。
git push <远程仓库名> <分支名>:将本地仓库的分支推送到远程仓库。
git pull <远程仓库名> <分支名>:从远程仓库拉取指定分支的最新内容并合并到本地分支。
11.如何进行 Git 的回滚操作,有哪些方式
使用 git reset 回滚:git reset --hard <提交哈希值> 可以将 HEAD 指针、本地仓库和工作区都回滚到指定的提交版本。git reset --soft <提交哈希值> 只移动 HEAD 指针和本地仓库,工作区的修改会保留在暂存区。git reset <提交哈希值>(默认是 --mixed 模式)会移动 HEAD 指针和本地仓库,工作区的修改会保留但不在暂存区。
使用 git revert 回滚:git revert <提交哈希值> 会创建一个新的提交,这个新提交的内容是撤销指定提交所做的修改。与 git reset 不同,git revert 不会删除历史提交记录。
12.在多人协作开发中,如何避免代码冲突
及时拉取最新代码:在开始新的开发工作前,先使用 git pull 拉取远程仓库的最新代码,确保本地代码是最新的。
合理划分分支:根据功能模块或任务创建不同的分支,避免多个开发者在同一个分支上同时进行大量修改。
频繁提交和合并:定期将自己的修改提交到本地仓库,并及时与主分支或其他相关分支进行合并,这样可以尽早发现并解决潜在的冲突。
使用代码审查:在合并代码前进行代码审查,确保代码质量和避免不必要的冲突。
13.如何对 Git 仓库进行清理,删除不必要的文件和分支
删除工作区中未跟踪的文件:使用 git clean -f 可以删除工作区中未被 Git 跟踪的文件。如果要删除未跟踪的目录,使用 git clean -fd。
删除本地分支:使用 git branch -d <分支名> 可以删除本地已经合并到主分支的分支。如果要强制删除未合并的分支,使用 git branch -D <分支名>。
删除远程分支:使用 git push <远程仓库名> --delete <分支名> 可以删除远程仓库上的指定分支。
14.简述 Git 钩子(Hooks)的作用和使用场景
Git 钩子是在 Git 执行特定操作(如提交、推送等)前后自动执行的脚本。它们可以帮助你在代码提交、合并等关键环节进行一些额外的检查和操作。
作用:实现自动化任务,如代码格式化、单元测试、代码审查等,确保代码质量和遵循团队规范。
使用场景:例如,在提交代码前运行 pre - commit 钩子,检查代码是否符合代码风格规范;在推送代码前运行 pre - push 钩子,执行单元测试,只有测试通过才能推送代码。
二、webpack
1、webpack是什么
webpack是一种前端资源构建工具,一个静态模块打包器(modoule bundler)
在webpack看来,前端的所有资源文件(js/json/css/img/less/…)都会作为模块处理。
他将根据模块的处理关系进行分析,打包成对应的静态资源(bundle)
2、webpack五个核心概念
Entry:入口(entry)指示webpack以哪个文件为入口起点开始打包,分析构建内部依赖图
Output:输出(output)指示webpack打包后的资源bundles输出到哪里去,以及如何命名
Loader 加载器(Loader)让webpack能够去处理非javascript文件(webpack自身只理解js)
Plugins 插件(plugins)可以用于范围更广的任务。插件的范围包括:从打包优化和压缩,一直到重新定义环境中的变量等。
Mode模式(mode)指示webpack使用相应模式的配置。分为development(开发模式)和production(生产模式)
3、Loader 和插件的区别是什么
loader是一个转换器,将A文件进行编译形成B文件,这里操作的是文件,比如将A.scss转换为A.css,单纯的文件装换过程,Loader 的本质是一个函数,它负责将某种格式的源文件(如 .js、.css、.png)转换为另一种格式或结构,从而让 Webpack 能够处理和打包这些资源。
plugin是一个扩张器,它丰富了webpack本身,针对是loader结束后,webpack打包的整个过程,它并不直接操作文件,而是基于事件机制工作,会监听webpack打包过程中的某些节点,执行广泛任务
如何实现一个vue-loader
Loader 本质上是一个函数,接收源文件内容作为参数,并返回转换后的内容。示例代码如下:
// my-loader.js
module.exports = function(source) {
// 对源文件内容进行处理
const newSource = source.replace('old', 'new');
return newSource;
};
在 webpack.config.js 中配置使用自定义 loader:
module.exports = {
module: {
rules: [
{
test: /\.js$/,
use: './my-loader.js'
}
]
}
}
自定义插件:
插件是一个具有 apply 方法的类,apply 方法接收 compiler 对象作为参数,通过监听 compiler 的不同钩子来执行特定任务。示例代码如下:
// my-plugin.js
class MyPlugin {
apply(compiler) {
compiler.hooks.compile.tap('MyPlugin', () => {
console.log('Compilation started...');
});
compiler.hooks.done.tap('MyPlugin', () => {
console.log('Compilation finished.');
});
}
}
module.exports = MyPlugin;
在 webpack.config.js 中使用自定义插件:
const MyPlugin = require('./my-plugin');
module.exports = {
plugins: [
new MyPlugin()
]
};
4、webpack.config.js作用
webpack的配置文件
作用:指示webpack干哪些活(当你运行webpack指令的时候,会加载里面的配置)
所有构建工具都是基于node.js平台运行的,模块默认采用common.js。
const { resolve } = require('path')
module.exports = {
// webpack配置
// 入口起点
entry: './src/index.js',
// 输出
output: {
// 输出文件名
filename: 'built.js',
// 输出路径
// __dirname nodejs的变量,代表当前文件的目录绝对路径
path: resolve(__dirname, 'build')
},
// loader的配置
module: {
rules: [
// 详细loader配置
// 不同文件必须配置不同loader处理
{
// 匹配哪些文件
test: /\.css$/,
// 使用哪些loader进行处理
use: [
// use数组中loader执行顺序:从右到左,从下到上,依次执行
// 创建style标签,将js中的样式资源插入进行,添加到head中生效
'style-loader',
// 将css文件变成commonjs模块加载js中,里面内容是样式字符串
'css-loader'
]
},
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
// 将less文件编译成css文件
// 需要下载less-loader和less
'less-loader'
]
}
],
},
// plugins的配置
plugins: [
// 详细plugins的配置
],
// 模式
mode: 'development'
}
图片资源打包
const {resolve} = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.js',
output: {
filename: 'built.js',
path: resolve(__dirname, 'build')
},
module: {
rules: [
{
test: /\.less$/,
use: ['style-loader', 'css-loader', 'less-loader']
},
{
// 问题:默认处理不了html中img图片
// 处理图片资源
test: /\.(jpg|png|gif)$/,
// 使用一个loader
// 下载url-loader file-loader
loader: 'url-loader',
options: {
// 图片大小小于8kb,就会被base64处理
// 优点:减少请求数量(减轻服务器压力)
// 缺点:图片体积会更大(文件请求速度更慢)
limit: 8 * 1024,
// 问题:因为url-loader默认使用es6模块化解析,而html-loader引入图片是commonjs
// 解析时会出现问题:[object Module]
// 解决:关闭url-loader的es6模块化,使用commonjs解析
// esModule: false
// 给图片进行重命名
// [hash:10]取图片的hash的前10位
// [ext]取文件原来扩展名
name: '[hash:10].[ext]'
}
},
{
test: /\.html$/,
// 处理html文件的img图片(负责引入img,从而能被url-loader进行处理)
loader: 'html-loader'
}
]
},
plugins: [
// plugin的配置
// html-webpack-plugin
// 功能:默认会创建一个空的HTML,自动引入打包输出的所有资源(JS/CSS)
// 需求:需要有结构的HTML文件
new HtmlWebpackPlugin({
// 复制 './src/index.html' 文件,并自动引入打包输出的所有资源(JS/CSS)
template: './src/index.html'
})
],
mode: 'development'
}
其他资源打包和自动更新
const {resolve} = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: './src/index.js',
output: {
filename: 'built.js',
path: resolve(__dirname, 'build')
},
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader', 'css-loader'
]
},
// 打包其他资源(除了html/js/css资源以外的资源)
{
// 排除css/js/html资源
exclude: /\.(css|js|html)$/,
loader: 'file-loader'
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html'
})
],
mode: 'development',
// 开发服务器 devServer:用来自动化(自动编译,自动打开浏览器,自动刷新浏览器)
// 特点:只会在内存中编译打包,不会有任何输出
// 启动devServer指令为:npx webpack serve
devServer: {
contentBase: resolve(__dirname, 'build'),
// 启动gzip压缩
compress: true,
// 端口号
port: 3000,
// 自动打开浏览器
open: true
}
}
5、生成环境的部署
提取css成单独文件
需下载mini-css-extract-plugin
插件
webpack.config.js需增加代码,module的rules需新增
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader'
]
},
plugins需新增
plugins: [
new MiniCssExtractPlugin({
filename: 'css/main.css'
})
],
6、如何使用 Webpack 处理 CSS 文件以及CSS兼容性处理
处理 CSS 文件
要使用 Webpack 处理 CSS 文件,需要安装并配置相应的 loader,一般使用 style-loader 和 css-loader。
安装:npm install style-loader css-loader --save-dev
配置 webpack.config.js:
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
}
]
}
};
css-loader 用于解析 CSS 文件中的 @import 和 url() 等语句,style-loader 用于将 CSS 代码插入到 HTML 的
CSS兼容性处理
需下载插件
postcss-loader
postcss-preset-env
新增配置文件postcss.config.js
module.exports = {
plugins: [
require('postcss-preset-env')
]
}
webpack.config.js新增内容
{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'postcss-loader',
}
]
},
帮postcss找到package.json中browserslist里面的配置,通过配置加载指定的css兼容性样式
"browserslist": {
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
],
"production": [
">0.2%",
"not dead",
"not op_mini all"
]
}
7、如何压缩css
需下载插件
optimize-css-assets-webpack-plugin
webpack.config.js需新增
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
plugins: [
new OptimizeCssAssetsWebpackPlugin()
],
8、js语法检查怎么配置
需下载插件
eslint-loader
eslint
eslint-config-airbnb-base
eslint-plugin-import
在package.json中新增
"eslintConfig": {
"extends": "airbnb-base"
}
在webpack.config.js的module中新增
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'eslint-loader',
options: {
// 自动修复eslint的错误
fix: true
}
}
忽略检查
// 下一行eslint所有规则都失效(下一行不进行eslint检查)
// eslint-disable-next-line
console.log(add(3, 5));
9、js兼容性处理
需下载插件
babel-loader
@babel/core
@babel/preset-env
webpack.config.js新增
/**
1. 基本js兼容性处理 --> @babel/preset-env
问题:只能转换基本语法,如promise不能转换
2. 全部js兼容性处理 --> @babel/polyfill。需在对应的js前面引入 import '@babel/polyfill'
问题:我只要解决部分兼容性问题,但是将所有兼容性代码全部引入,体积太大了
3. 需要做兼容性处理的就做:按需加载 ---> core-js
*/
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
// 按需加载
useBuiltInt: 'usage',
// 指定core.js版本
corejs: {
version: 3
},
// 指定兼容性做到哪个版本浏览器
targets: {
chrome: '60',
firefox: '60',
ie: '9',
safari: '10',
edge: '17'
}
}
]
]
}
}
10、js的压缩
生产环境下会自动压缩js代码
mode: 'production'
11、html的压缩
在webpack.config.js中新增
new HtmlWebpackPlugin({
template: './src/index.html',
minify: {
// 移除空格
collapseWhitespace: true,
// 移除注释
removeComments: true
}
}),
12、如何使用 Webpack 优化生产环境的构建
使用生产模式:在 webpack.config.js 中设置 mode: ‘production’,Webpack 会自动开启一些优化,如代码压缩、Tree Shaking 等。
压缩代码:使用 TerserPlugin 压缩 JavaScript 代码,MiniCssExtractPlugin 提取并压缩 CSS 代码。示例配置如下:
const TerserPlugin = require('terser-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
mode: 'production',
optimization: {
minimizer: [
new TerserPlugin()
]
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css'
})
],
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader']
}
]
}
};
Tree Shaking:确保使用 ES6 模块语法,Webpack 在生产模式下会自动进行 Tree Shaking,移除未使用的代码。
代码分割:使用前面提到的代码分割技术,减少初始加载时间。
13、Webpack 热更新(Hot Module Replacement,HMR)的原理是什么,如何配置
原理:Webpack 热更新允许在不刷新整个页面的情况下更新模块。它通过 Webpack Dev Server 与浏览器建立 WebSocket 连接,当代码发生变化时,Webpack 会重新编译发生变化的模块,并通过 WebSocket 通知浏览器。浏览器收到通知后,会使用 HMR 运行时替换旧的模块。
配置:
安装 webpack-dev-server:npm install webpack-dev-server --save-dev
在 webpack.config.js 中开启 HMR:
const webpack = require('webpack');
module.exports = {
devServer: {
hot: true
},
plugins: [
new webpack.HotModuleReplacementPlugin()
]
};
在代码中可以添加对 HMR 的处理,例如在入口文件中:
if (module.hot) {
module.hot.accept();
}
16、简述 Webpack 的构建流程
初始化参数:从配置文件和命令行中读取并合并参数,得到最终的配置对象。
开始编译:根据配置对象创建 Compiler 对象,开始执行编译过程。
解析模块:从入口文件开始,递归地解析所有依赖的模块,使用相应的 loader 对模块进行转换。
生成依赖图:将所有解析后的模块按照依赖关系生成一个依赖图。
打包模块:根据依赖图,将所有模块打包成一个或多个文件。
输出文件:将打包后的文件输出到指定的目录。
17、webpack如何找到依赖关系的
1、webpack-bundle-analyzer(可视化)
安装和使用
npm install --save-dev webpack-bundle-analyzer
在webpack.config.js中:
let BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [new BundleAnalyzerPlugin()]
}
启动服务:
生产环境查看:npm run build --report 或 正常build 即可启动查看器
开发环境查看:webpack -p --progress 或启动正常devServer服务即可启动查看器!
18、webpack如何配置
- 创建项目文件夹, 名字自起, 但路径名不要包含中文, 以及项目名也不要叫"webpack", 并且不要包含大写字母.
- 接下来创建并编写配置文件. 首先我们先介绍几个配置文件的参数
entry: 是 页面入口文件配置 (html文件引入唯一的js 文件)
output:对应输出项配置
path :入口文件最终要输出到哪里,
filename:输出文件的名称
publicPath:公共资源路径
- 在你的项目目录下创建webpack.config.js配置文件, 通过这个文件进行webpack的配置, 并且还要创建一些路径保存基本文件. 例如:
- 在src的js下创建一个入口文件, 我创建的叫做entry.js, 在项目目录再创建一个index.html用来调试使用. 编写webpack.config.js文件,
19.解释 Webpack 的代码分割(Code Splitting)及其实现方式
代码分割是一种优化策略,它允许将应用程序分割成多个较小的文件,实现按需加载,从而减少初始加载时间。实现方式主要有以下几种:
入口起点分割:通过配置多个入口点,将不同的代码块打包成不同的文件。例如:
module.exports = {
entry: {
main: './src/index.js',
vendor: './src/vendor.js'
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
动态导入(Dynamic Imports):使用 ES6 的动态导入语法 import() 实现按需加载。例如:
button.addEventListener('click', () => {
import('./module').then(module => {
// 使用模块
});
});
使用 splitChunks 配置:Webpack 4+ 提供了 splitChunks 配置选项,用于自动分割公共代码和第三方库。示例配置如下:
module.exports = {
optimization: {
splitChunks: {
chunks: 'all'
}
}
};
20.如何使用 Webpack 进行图片处理
可以使用 file-loader 或 url-loader 来处理图片。
file-loader:将图片复制到输出目录,并返回图片的路径。安装:npm install file-loader --save-dev,配置如下:
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/'
}
}
]
}
]
}
};
url-loader:可以将小图片转换为 Base64 编码的字符串,减少 HTTP 请求。它是 file-loader 的封装,安装:npm install url-loader --save-dev,配置如下:
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 8192, // 小于 8KB 的图片转换为 Base64
name: '[name].[ext]',
outputPath: 'images/'
}
}
]
}
]
}
};
21.如何监控 Webpack 的构建性能,有哪些优化策略
监控构建性能:
- 使用 webpack --profile --json > stats.json 命令生成构建统计信息,然后使用webpack-bundle-analyzer 工具分析这些信息,可视化展示各个模块的大小和依赖关系。
- 在webpack.config.js 中使用 SpeedMeasurePlugin 插件,统计每个 loader 和插件的执行时间。
优化策略:
缓存:使用 cache-loader 缓存 loader 的处理结果,减少重复编译。
并行处理:使用 thread-loader 开启多线程处理,提高构建速度。
排除不必要的文件:在 include 和 exclude 中配置规则,排除不需要处理的文件。
懒加载模块:使用动态导入实现模块的懒加载,减少初始加载的代码量。
22.在微前端架构中,Webpack 可以发挥什么作用
模块打包:将各个微应用打包成独立的文件,方便部署和加载。
代码分割:对微应用进行代码分割,实现按需加载,提高应用的加载性能。
资源隔离:通过 Webpack 的配置,确保各个微应用的资源(如 CSS、JavaScript 等)相互隔离,避免冲突。
模块联邦:Webpack 5 引入了模块联邦功能,允许不同的微应用之间共享模块,实现更灵活的微前端架构。例如,一个微应用可以直接使用另一个微应用暴露的模块,而无需重复打包。
23.如何使用 Webpack 处理 TypeScript 文件
要使用 Webpack 处理 TypeScript 文件,需要安装并配置相应的 loader。
安装依赖:npm install typescript ts-loader --save-dev
创建 tsconfig.json 文件,配置 TypeScript 编译选项。
在 webpack.config.js 中配置 ts-loader:
const path = require('path');
module.exports = {
entry: './src/index.ts',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
resolve: {
extensions: ['.ts', '.js']
},
module: {
rules: [
{
test: /\.ts$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
}
};
这样 Webpack 就可以处理 TypeScript 文件,并将其编译为 JavaScript 代码进行打包。
24.postcss-loader是什么作用,style-loader,css-loader,less-loader分别做了哪些事情
在前端工程化中,postcss-loader、style-loader、css-loader 和 less-loader 是处理 CSS 相关资源的核心 Loader,它们在 Webpack 构建流程中分工协作,共同完成样式资源的编译、转换和注入。以下是它们的具体作用和执行顺序:
24.1各 Loader 的核心功能
24.1.1less-loader
作用:将 Less/Sass 等 CSS 预处理器语法编译为普通 CSS。
原理:调用 Less/Sass 编译器,处理嵌套规则、变量、函数等预处理器特性。
示例配置:
{
test: /\.less$/,
use: ['style-loader', 'css-loader', 'less-loader']
}
输入:Less 代码(如 @color: red; .btn { color: @color; })
输出:普通 CSS(如 .btn { color: red; })
24.1.2 css-loader
作用:解析 CSS 文件中的 @import 和 url() 等资源引入语法,处理 CSS 模块(CSS Modules)和 Source Map。
原理:将 CSS 文件转换为 JavaScript 模块,支持 @import 嵌套处理和资源路径解析。
关键配置:
{
loader: 'css-loader',
options: {
modules: true, // 启用 CSS Modules
importLoaders: 1 // 指定前面还有几个 Loader 参与处理 @import
}
}
输入:CSS 代码(如 @import 'reset.css'; .btn { background: url(icon.png); })
输出:JavaScript 对象表示的 CSS 规则(如 exports = { "btn": "btn_123abc" })
24.1.3. postcss-loader
作用:使用 PostCSS 插件对 CSS 进行转换(如添加浏览器前缀、CSS 压缩、CSS 模块化等)。
原理:通过插件机制处理 CSS,常见插件包括:
autoprefixer:自动添加浏览器前缀(如 -webkit-、-moz-)。
cssnano:压缩 CSS 代码。
postcss-preset-env:将现代 CSS 转换为浏览器兼容的版本。
配置示例(postcss.config.js):
module.exports = {
plugins: [
require('autoprefixer')({ browsers: ['last 2 versions'] }),
require('cssnano')
]
}
输入:普通 CSS(如 display: flex;)
输出:处理后的 CSS(如 display: -webkit-box; display: flex;)
24.1.4. style-loader
作用:将 CSS 代码以style标签形式注入到 HTML 文档中。
原理:在运行时通过 JavaScript 创建
{
loader: 'style-loader',
options: {
injectType: 'singletonStyleTag' // 合并所有 CSS 到单个 <style> 标签
}
}
输入:JavaScript 模块形式的 CSS
输出:HTML 中的 <style> 标签(如 <style>.btn{color:red}</style>)
24.2执行顺序与协作流程
Loader 的执行顺序是从后往前,即:
less-loader → css-loader → postcss-loader → style-loader
示例流程
Webpack 遇到 .less 文件,调用 less-loader。
less-loader 将 Less 代码编译为 CSS(如处理变量、嵌套规则)。
css-loader 解析 CSS 中的 @import 和 url(),生成 JavaScript 模块。
postcss-loader 使用 autoprefixer 等插件优化 CSS(如添加前缀)。
style-loader 将最终 CSS 注入到 HTML 的
24.3常见场景与优化
24.3.1. 生产环境优化:提取 CSS 到独立文件
问题:style-loader 将 CSS 内联到 JavaScript 中,导致首屏加载延迟。
解决方案:使用 mini-css-extract-plugin 替代 style-loader,将 CSS 提取到独立文件:
{
test: /\.less$/,
use: [
MiniCssExtractPlugin.loader, // 替代 style-loader
'css-loader',
'postcss-loader',
'less-loader'
]
}
24.3.2 CSS Modules 实现局部作用域
配置:
{
loader: 'css-loader',
options: {
modules: {
localIdentName: '[name]__[local]--[hash:base64:5]' // 自定义类名生成规则
}
}
}
使用:
import styles from './button.less';
<button className={styles.btn}>Click</button>
24.3.3 自定义 PostCSS 插件链
postcss.config.js 示例:
module.exports = (ctx) => ({
plugins: [
require('postcss-preset-env')(ctx.options), // 转换现代 CSS
require('autoprefixer'), // 添加前缀
ctx.env === 'production' ? require('cssnano') : false // 生产环境压缩
]
});
24.4为什么需要多个 CSS Loader?它们的分工是什么?
24.4.1分工:
less-loader:编译预处理器语法。
css-loader:解析 CSS 中的资源引用。
postcss-loader:转换和优化 CSS。
style-loader:动态注入 CSS 到 DOM。
必要性:单一 Loader 无法完成所有功能(如编译 Less、添加前缀、处理模块化)。
24.4.2如何处理 CSS 中的图片资源路径?
方案:
配合 file-loader 或 url-loader 处理 url() 引用的图片。
示例配置:
{
test: /\.(png|jpg)$/,
use: 'url-loader?limit=8192' // 小于 8KB 的图片转为 base64
}
24.4.3CSS Modules 和 Scoped CSS 的区别?
CSS Modules:通过编译时生成唯一类名(如 button_primary_123)实现局部作用域,适用于组件化开发。
Scoped CSS:通过 Vue 等框架的 scoped 属性实现,在 DOM 节点添加唯一属性(如 data-v-123),属于运行时方案。
24.4.3如何优化 CSS 构建性能?
使用 cache-loader 缓存 Loader 处理结果。
在生产环境使用 cssnano 压缩 CSS。
对于大型项目,考虑使用 thread-loader 多线程处理 CSS。
25.用过哪些plugin,举例说明,plugin的内部实现是?
25.1常见 Plugin 及其应用场景
25.1.1. HtmlWebpackPlugin
作用:自动生成 HTML 文件并注入打包后的资源(如 JS、CSS)。
应用场景:
动态生成 HTML 模板,避免手动维护资源路径。
多页面应用中自动创建多个 HTML 文件。
配置示例:
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html', // 源模板文件
filename: 'index.html', // 输出文件名
minify: true // 压缩HTML
})
]
};
25.1.2. MiniCssExtractPlugin
作用:将 CSS 提取到独立文件,替代style-loader的内联方式。
应用场景:
生产环境优化,减少 JS 文件体积,支持 CSS 并行加载。
配置示例:
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
plugins: [
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css' // 输出文件名
})
],
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader'] // 替换 style-loader
}
]
}
};
25.1.3. CleanWebpackPlugin
作用:在每次构建前清理输出目录,避免旧文件残留。
配置示例:
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
plugins: [
new CleanWebpackPlugin() // 默认清理 output.path 目录
]
};
25.1.4. DefinePlugin
作用:在编译时定义全局变量,常用于环境配置。
配置示例:
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production'),
API_URL: '"https://api.example.com"' // 注意引号嵌套
})
]
};
25.1.5. CopyWebpackPlugin
作用:将静态文件(如图片、字体)复制到输出目录。
配置示例:
const CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = {
plugins: [
new CopyWebpackPlugin({
patterns: [
{ from: 'public', to: 'public' } // 复制 public 目录到输出目录
]
})
]
};
25.2Plugin 的内部实现原理
25.2.1. 核心机制:事件钩子(Hooks)
Webpack 通过发布 - 订阅模式实现插件系统,主要包含以下组件:
Compiler:编译核心对象,包含完整的 Webpack 生命周期(如编译开始、结束)。
Compilation:单次编译过程的上下文,包含模块、依赖、资源等信息。
Hooks:各种生命周期事件(如compile、emit、afterEmit)。
25.2.2. Plugin 的基本结构
一个 Plugin 是一个包含apply方法的类,该方法接收compiler对象作为参数:
class MyPlugin {
constructor(options) {
this.options = options;
}
apply(compiler) {
// 监听特定钩子事件
compiler.hooks.compile.tap('MyPlugin', (compilationParams) => {
console.log('编译开始前执行...');
});
// 异步钩子使用 tapAsync 或 tapPromise
compiler.hooks.emit.tapAsync('MyPlugin', (compilation, callback) => {
// 处理编译产物(如修改输出文件)
callback(); // 完成后调用回调
});
}
}
module.exports = MyPlugin;
25.2.3. 关键钩子类型
同步钩子:使用tap注册,按顺序执行(如compile、make)。
异步钩子:
tapAsync:通过回调函数异步执行。
tapPromise:通过 Promise 异步执行(推荐)。
常见钩子:
25.3自定义 Plugin 示例:文件后缀替换
以下插件会将所有输出文件名的.js后缀替换为.bundle.js:
class RenameJsPlugin {
apply(compiler) {
// 监听 emit 钩子(生成文件前)
compiler.hooks.emit.tapPromise('RenameJsPlugin', (compilation) => {
// 获取所有输出文件
const assets = Object.keys(compilation.assets);
// 遍历并修改 .js 文件的文件名
for (const asset of assets) {
if (asset.endsWith('.js')) {
const newName = asset.replace('.js', '.bundle.js');
// 获取文件内容
const source = compilation.assets[asset].source();
const size = compilation.assets[asset].size();
// 删除原文件,添加新文件
delete compilation.assets[asset];
compilation.assets[newName] = {
source: () => source,
size: () => size
};
}
}
return Promise.resolve();
});
}
}
module.exports = RenameJsPlugin;
26webpack chunk和bundle的区别是?
26.1核心概念对比
术语 定义 产生阶段 示例
Chunk 代码分割(Code Splitting)后的逻辑块,是Webpack内部的抽象概念,产生阶段是编译时(Compilation),比如main、vendors、动态导入的模块
Bundle 最终输出的物理文件,由一个或多个 Chunk 合并生成,产生阶段是输出时(Output),比如 main.js、chunk-123.js、style.css
26.2深入理解 Chunk
26.2.1. 三种类型的 Chunk
Entry Chunk
由entry配置直接生成,包含运行时代码(Runtime)和入口模块及其依赖。
// webpack.config.js
entry: {
main: './src/index.js', // 生成 main 入口 chunk
admin: './src/admin.js' // 生成 admin 入口 chunk
}
Normal Chunk
通过动态导入(import(‘./module.js’))或SplitChunksPlugin生成的独立逻辑块。
// 动态导入生成 normal chunk
button.addEventListener('click', () => {
import('./dialog.js').then(module => {
module.open();
});
});
Initial Chunk
页面加载时必须立即加载的 Chunk(包含入口 Chunk 和被同步引用的 Chunk)。
26.3深入理解 Bundle
26.3.1生成规则
一对一:多数情况下,一个 Chunk 对应一个 Bundle。
// 配置
output: {
filename: '[name].[contenthash].js', // 如 main.123abc.js
chunkFilename: '[id].[contenthash].js' // 如 1.456def.js
}
// 结果
main chunk → main.123abc.js
动态导入的 chunk → 1.456def.js
合并:通过optimization.splitChunks配置,多个 Chunk 可能合并为一个 Bundle。
optimization: {
splitChunks: {
chunks: 'all',
minSize: 0,
name: 'vendor' // 将所有依赖合并为 vendor.js
}
}
拆分:一个 Chunk 可能被拆分为多个 Bundle(如 CSS 被单独提取)。
// 使用 MiniCssExtractPlugin
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader']
}
// 结果
main chunk → main.js 和 main.css
26.4关键区别总结
26.5
- 合理拆分 Chunk
原则:
将核心代码与非关键代码分离(如动态导入用户可能不使用的功能)。
将第三方库单独打包(如 React、Vue),利用浏览器缓存。 - 控制 Bundle 大小
工具:
使用webpack-bundle-analyzer分析 Bundle 组成。
通过splitChunks配置maxSize限制单个 Bundle 大小。 - 优化加载顺序
策略:
对关键资源使用preload或prefetch。
避免首屏加载过多 Initial Chunk 对应的 Bundle。
总结
Chunk是 Webpack 编译时的逻辑单元,代表代码分割后的功能块。
Bundle是最终输出的物理文件,由 Chunk 组合生成。
理解两者区别对优化资源加载(如按需加载、缓存策略)至关重要。
27webpack打包实现按需加载?如antd如何打包只打引入的组件?
27.1按需加载的核心原理
Webpack 通过 动态导入(Dynamic Import) 和 SplitChunksPlugin 实现按需加载:
动态导入:
import('./module.js').then(module => {
// 模块加载完成后执行
});
生成独立的 Chunk(如 1.js),仅在调用时加载。
对应 HTML 中动态创建script标签。
SplitChunksPlugin:
自动拆分公共依赖,避免重复打包:
optimization: {
splitChunks: {
chunks: 'all',
}
}
27.2Ant Design 按需打包的实现方案
27.2.1. 手动按需引入(基础方案)
// 不推荐:全量引入(体积大)
import { Button } from 'antd';
// 推荐:手动按需引入(需配置 resolve.alias)
import Button from 'antd/es/button';
import 'antd/es/button/style/css'; // 单独引入 CSS
27.2.2 自动按需引入(推荐方案)
使用 babel-plugin-import 或 unplugin-vue-components(Vue 项目)自动转换导入语句:
// .babelrc 配置
{
"plugins": [
[
"import",
{
"libraryName": "antd",
"libraryDirectory": "es",
"style": true // 自动引入 CSS/less
}
]
]
}
// 转换前
import { Button } from 'antd';
// 转换后
import Button from 'antd/es/button';
import 'antd/es/button/style';
27.2.3 Tree Shaking(优化未使用的组件)
确保 Webpack 配置支持 Tree Shaking:
// webpack.config.js
module.exports = {
mode: 'production', // 启用生产模式
optimization: {
usedExports: true, // 标记未使用的导出
minimize: true // 压缩时移除未使用代码
}
};
三、NPM
1.npm i的几种方式区别
2.如何创建自己的npm包
首先在npm网站上注册一个账号
npm网站地址:https://www.npmjs.com/
npm网站注册地址:https://www.npmjs.com/signup
注册完毕,回到我们的电脑。Windows直接cmd到命令行:
//输入以下命令,会提示输入用户名、密码、邮箱,这些都是注册时填写过的。
npm login
创建一个testxxxxx文件夹,cd到testxxxxx文件夹中,然后下载基础配置文件:
//输入以下命令,会提示配置包的相关信息,名称版本等等,都是包的基本配置信息
npm init
配置完毕开始写自己的包内代码:
//创建一个index.js文件,文件内的代码如下,直接输出123456789
module.exports = 123456789;
保存完毕,一个简单的包就开发好了,就可以直接发布到npm上供大家下载。下面就介绍发布:
//退出当前文件夹,开始命令行发布包,命令如下:
npm publish testxxxxx
发布完毕,在npm网站上搜索,就可以搜索到自己刚刚发布的包了。要验证自己的安装包的话,直接正常的下载就好了。
验证下载:
//
npm install testxxxxx