一、Git
- git 和 svn 的区别
- 经常使用的 git 命令?
git init // 新建 git 代码库 git add // 添加指定文件到暂存区 git add . git rm // 删除工作区文件,并且将这次删除放入暂存区 git commit -m [message] // 提交暂存区到仓库区 git branch // 列出所有分支 git branch <分支名字> // 创建分支 git branch -d <分支名字> // 删除分支 git checkout -b [branch] // 新建一个分支,并切换到该分支 git checkout <分支名字> // 切换分支 git status // 显示有变更文件的状态 git push origin master // 上传本地指定分支到远程仓库 git pull [branch] // 取回远程仓库的变化,并与本地分支合并 // 将自己本地的项目和远程仓库建立联系,执行以下两个代码关联起来 git remote add origin https://github.com/wanglu458512/supermall.git git push -u origin master - git pull 和 git fetch 的区别
git fetch 只是将远程仓库的变化下载下来,并没有和本地分支合并。 git pull 会将远程仓库的变化下载下来,并和当前分支合并。 - git rebase 和 git merge 的区别
git merge 和 git rebase 都是用于分支合并,关键在 commit 记录的处理上不同: git merge 会新建一个新的 commit 对象,然后两个分支以前的 commit 记录都指向这个新 commit 记录。这种方法会保留之前每个分支的 commit 历史。 git rebase 会先找到两个分支的第一个共同的 commit 祖先记录,然后将提取当前分支这之后的所有 commit 记录,然后将这个 commit 记录添加到目标分支的最新提交后面。经过这个合并后,两个分支合并后的 commit 记录就变为了线性的记录了。 - 实际开发
添:将修改的内容添加到本地暂存区 git add。 提:将本地暂存区中的内容提交到本地代码库 git commit -m ‘description’。 拉:同步,拉取远程代码库中的内容,在多人协同开发中十分的重要,因为假如事先没有同步更新到最新版本有可能会覆盖别人修改的东西,假如拉取后有冲突直接使用VS Code解决冲突即可 git pull。 推:将本地代码库中的内容推送到远程代码仓库 git push。
二、Webpack
- webpack与grunt、gulp的不同?
Grunt、Gulp是基于任务运?的?具: 它们会?动执?指定的任务,就像流?线,grunt/gulp也被称为前端自动化任务管理工具,grunt/gulp更加强调的是前端流程的自动化,模块化不是它的核心 Webpack是基于模块化打包的?具: ?动化处理模块,webpack把?切当成模块,当 webpack 处理应?程序时,它会递归地构建?个依赖关系图 (dependency graph),其中包含应?程序需要的每个模块,然后将所有这些模块打包成?个或多个 bundle。 - webpack作用?
模块打包。可以将不同模块的文件打包整合在一起,并且保证它们之间的引用正确,执行有序。利用打包我们就可以在开发的时候根据我们自己的业务自由划分文件模块,保证项目结构的清晰和可读性。 编译兼容。在前端的“上古时期”,手写一堆浏览器兼容代码一直是令前端工程师头皮发麻的事情,而在今天这个问题被大大的弱化了,通过webpack的Loader机制,可以编译转换诸如.less, .vue, .jsx这类在浏览器无法识别的格式文件,让我们在开发的时候可以使用新特性和新语法做开发,提高开发效率。 能力扩展。通过webpack的Plugin机制,我们在实现模块化打包和编译兼容的基础上,可以进一步实现诸如按需加载,代码压缩等一系列功能,帮助我们进一步提高自动化程度,工程效率以及打包输出的质量。 - 有哪些常?的Loader?
file-loader:把?件输出到?个?件夹中,在代码中通过相对 URL 去引?输出的?件 url-loader:和 file-loader 类似,但是能在?件很?的情况下以 base64 的?式把?件内容注?到代码中去 source-map-loader:加载额外的 Source Map ?件,以?便断点调试 image-loader:加载并且压缩图??件 babel-loader:把 ES6 转换成 ES5 css-loader:加载 CSS,?持模块化、压缩、?件导?等特性 style-loader:把 CSS 代码注?到 JavaScript 中,通过 DOM 操作去加载 CSS。 eslint-loader:通过 ESLint 检查 JavaScript 代码 less-loader:把less转换为css 在Webpack中,loader的执行顺序是从右向左执行的 - 有哪些常?的Plugin?
plugin是插件,它是对webpack本身的扩展,是一个扩展器 plugin的使用过程: 步骤一:通过npm安装需要使用的plugins(某些webpack已经内置的插件不需要安装) 如npm install html-webpack-plugin --save-dev 步骤二:在webpack.config.js中的plugins中配置插件。 new webpack.BannerPlugin 添加版权 new htmlWebpackPlugin打包HTML:自动生成一个index.html文件(可以指定模板来生成),将打包的js文件,自动通过script标签插入到body中 uglifyjs-webpack-plugin JS压缩的,不支持 ES6 压缩 (Webpack4 以前) terser-webpack-plugin: 支持压缩 ES6 (Webpack4) webpack-parallel-uglify-plugin: 多核压缩,提?压缩速度 webpack-bundle-analyzer: 可视化webpack输出?件的体积 mini-css-extract-plugin: CSS提取到单独的?件中,?持按需加载 - bundle,chunk,module是什么?
打包 webpack .src/main.js -o ./dist/bundle.js bundle:是由webpack打包出来的?件; chunk:代码块,?个chunk由多个模块组合?成,?于代码的合并和分割; module:是开发中的单个模块,在webpack的世界,?切皆模块,?个模块对应?个?件,webpack会从配置的 entry中递归开始找出所有依赖的模块。 - Loader和Plugin的不同?
不同的作?: Loader主要用于转换某些类型的模块,它是一个转换器。Webpack将?切?件视为模块,但是webpack原?是只能解析js?件,如果想将其他?件也打包的话,就会?到 loader 。所以Loader的作?是让webpack拥有了加载和解析?JavaScript?件的能?。 Plugin直译为"插件"。Plugin可以扩展webpack的功能,让webpack具有更多的灵活性。 在 Webpack 运?的?命周期中会?播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。 不同的?法: Loader在 module.rules 中配置,也就是说他作为模块的解析规则?存在。 类型为数组,每?项都是?个 Object ,??描述了对于什么类型的?件( test ),使?什么加载( loader )和使?的参数( options ) Plugin在 plugins 中单独配置。 类型为数组,每?项是?个 plugin 的实例,参数都通过构造函数传?。
webpack的构建流程?
Webpack 的运?流程是?个串?的过程,整个打包流程: 初始化参数:解析webpack配置参数,合并shell传入和webpack.config.js文件配置的参数,形成最后的配置结果; 开始编译:上一步得到的参数初始化compiler对象,注册所有配置的插件,插件 监听webpack构建生命周期的事件节点,做出相应的反应,执行对象的run方法开始执行编译; 确定入口:从配置的entry入口,开始解析文件构建AST语法树,找出依赖,递归下去; 编译模块:递归中根据文件类型和loader配置,调用所有配置的loader对文件进行转换,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理; 完成模块编译并输出:递归完事后,得到每个文件结果,包含每个模块以及他们之间的依赖关系,根据entry或分包配置生成代码块chunk; 输出完成:输出所有的chunk到文件系统;
其中文件的解析与构建是一个比较复杂的过程,在webpack源码中主要依赖于compiler和compilation两个核心对象实现。compiler和compilation是Webpack两个非常核心的对象,其中compiler暴露了和 Webpack整个生命周期相关的钩子(compiler-hooks),而compilation则暴露了与模块和依赖有关的粒度更小的事件钩子(Compilation Hooks)。 compiler对象是一个全局单例,他负责把控整个webpack打包的构建流程。 compilation对象是每一次构建的上下文对象,它包含了当次构建所需要的所有信息,每次热更新和重新构建,compiler都会重新生成一个新的compilation对象,负责此次更新的构建过程。 而每个模块间的依赖关系,则依赖于AST语法树。每个模块文件在通过Loader解析完成之后,会通过acorn库生成模块代码的AST语法树,通过语法树就可以分析这个模块是否还有依赖的模块,进而继续循环执行下一个模块的编译解析。 最终Webpack打包出来的bundle文件是一个立即执行函数。
是否写过loader,简述一下思路?
Webpack最后打包出来的成果是一份Javascript代码,实际上在Webpack内部默认也只能够处理JS模块代码,在打包过程中,会默认把所有遇到的文件都当作 JavaScript代码进行解析,因此当项目存在非JS类型文件时,我们需要先对其进行必要的转换,才能继续执行打包任务,这也是Loader机制存在的意义。
module.exports = {
module: {
rules: [
{
test: /^your-regExp$/,
use: [
{
loader: 'loader-name-A',
},
...
通过配置可以看出,针对每个文件类型,loader是支持以数组的形式配置多个的,因此当Webpack在转换该文件类型的时候,会按顺序链式调用每一个loader,前一个loader返回的内容会作为下一个loader的入参。因此loader的开发需要遵循一些规范,比如返回值必须是标准的JS代码字符串,以保证下一个loader能够正常工作,同时在开发上需要严格遵循“单一职责”,每个Loader只做?种"转义"?作。 每个Loader的拿到的是源?件内容(source),可以通过返回值的?式将处理后的内容输出,也可以调? this.callback() ?法,将内容返回给webpack。 还可以通过this.async() ?成?个 callback 函数,再?这个callback将处理后的内容输出出去。 loader函数中的this上下文由webpack提供,可以通过this对象提供的相关属性,获取当前loader需要的各种信息数据。https://www.webpackjs.com/api/loaders/#%E7%A4%BA%E4%BE%8B
是否写过plugins,简述一下思路?
webpack在运?的?命周期中会?播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。 compiler 暴露了和 Webpack 整个生命周期相关的钩子 compilation 暴露了与模块和依赖有关的粒度更小的事件钩子插件 需要在其原型上绑定apply方法,才能访问 compiler 实例传给每个插件的 compiler 和 compilation对象都是同一个引用,若在一个插件中修改了它们身上的属性,会影响后面的插件找出合适的事件点去完成想要的功能 emit 事件发生时,可以读取到最终输出的资源、代码块、模块及其依赖,并进行修改(emit 事件是修改 Webpack 输出资源的最后时机)watch-run 当依赖的文件发生变化时会触发 异步的事件需要在插件处理完任务时调用回调函数通知 Webpack 进入下一个流程,不然会卡住 webpack 插件由以下组成: 一个 JavaScript 命名函数。 在插件函数的 prototype 上定义一个 apply 方法。 指定一个绑定到 webpack 自身的事件钩子。 处理 webpack 内部实例的特定数据。 功能完成后调用 webpack 提供的回调
```javascript
// 一个 JavaScript 命名函数。
function MyExampleWebpackPlugin() {
};
// 在插件函数的 prototype 上定义一个 `apply` 方法。
MyExampleWebpackPlugin.prototype.apply = function(compiler) {
compiler.plugin('webpacksEventHook', function(compilation , callback) {
console.log("This is an example plugin!!!");
callback();
});
};
https://juejin.cn/post/6844904094281236487#heading-17
source map是什么?
source map 是将编译、打包、压缩后的代码映射回源代码的过程。打包压缩后的代码不具备良好的可读性,想要调试源码就需要 soucre map。
模块打包原理知道吗?
Webpack 实际上为每个模块创造了一个可以导出和导入的环境,本质上并没有修改 代码的执行逻辑,代码执行顺序与模块加载顺序也完全一致。
热更新原理?
webpack提供了一个可选的本地开发服务器,这个本地服务器基于node.js搭建,内部使用express框架,可以实现我们想要的让浏览器自动刷新显示我们修改后的结果。webpack-dev-server Webpack 的热更新又称热替换(Hot Module Replacement),缩写为 HMR。 这个机制可以做到不用刷新浏览器而将新变更的模块替换掉旧的模块。 HMR的核心就是客户端从服务端拉去更新后的文件,准确的说是 chunk diff (chunk 需要更新的部分),实际上 WDS 与浏览器之间维护了一个 Websocket,当本地资源发生变化时,WDS 会向浏览器推送更新,并带上构建时的 hash,让客户端与上一次资源进行对比。客户端对比出差异后会向 WDS 发起 Ajax 请求来获取更改内容(文件列表、hash),这样客户端就可以再借助这些信息继续向 WDS 发起 jsonp 请求获取该chunk的增量更新。 后续的部分(拿到增量更新之后如何处理?哪些状态该保留?哪些又需要更新?)由 HotModulePlugin 来完成,HotModulePlugin 将会对新旧模块进行对比,决定是否更新模块,在决定更新模块后,检查模块之间的依赖关系,更新模块的同时更新模块间的依赖引用。https://zhuanlan.zhihu.com/p/30669007
webpack.config.js
const path=require('path')
const { VueLoaderPlugin } = require('vue-loader')
const webpack=require('webpack')
const htmlWebpackPlugin=require('html-webpack-plugin')
const uglicyJsPlugin=require('uglifyjs-webpack-plugin')
const devServer=require('webpack-dev-server')
module.exports={
entry:'./src/main.js',
output:{
path:path.resolve(__dirname,'dist'),
filename:'bundle.js',
},
module:{
rules: [
{
test: /\.css$/i,
use: ["style-loader", "css-loader"],
},
{
test: /\.less$/,
use: [{
loader: "style-loader",
}, {
loader: "css-loader"
}, {
loader: "less-loader",
}]
},
{
test: /\.(png|jpg|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 13000,
name: 'img/[name].[hash:8].[ext]'
},
},
],
},
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
},
{
test:/\.vue$/,
use:['vue-loader']
}
],
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
},
plugins: [
new VueLoaderPlugin(),
new webpack.BannerPlugin('最终版权归wanglu所有'),
new htmlWebpackPlugin({
template:'index.html'
}),
new uglicyJsPlugin()
],
devServer:{
contentBase:"./dist",
inline:true
}
}
webpack如何打包css,html这些文件,内部是如何
安装webpack npm install webpack --save-dev 初始化项目 npm init,生成packet.json 打包:在项目中建立src和dist文件夹,dist用于存放打包好的文件,src用于存放源文件。执行 webpack src/index.js dist/bundle.js会把index.js文件打包好放入dist的文件夹中。在index.html中就可以直接引入打包好的js文件了。 注意:为了避免每次打包的时候都写入口和出口参数,创建 webpack.config.js文件,这样的话 每次打包就写 webpack 就可以了。
const path = require('path')
module.exports = {
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
}
为了避免每次都写那么长的代码,在package.json文件夹中引入以下代码,在执行webpack的时候 可以用 npm run build代替
"scripts": {
"build": "webpack"
}
打包HTML: js文件打包好了,但是我们不可能每次在html文件中手动引入打包好的js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
mode:'development',
entry: path.resolve(__dirname,'../src/main.js'),
output: {
filename: '[name].[hash:8].js',
path: path.resolve(__dirname,'../dist')
},
plugins:[
new HtmlWebpackPlugin({
template:path.resolve(__dirname,'../public/index.html')
})
]
}
为了缓存,你会发现打包好的js文件的名称每次都不一样。webpack打包出来的js文件我们需要引入到html中,但是每次我们都手动修改js文件名显得很麻烦,因此我们需要一个插件来帮我们完成这件事情 npm i -D html-webpack-plugin plugins配置如上 new htmlWebpackPlugin打包HTML:自动生成一个index.html文件(可以指定模板来生成),将打包的js文件,自动通过script标签插入到body中
打包CSS 入口文件是js,所以在入口文件中引入css文件 require(’./css/normal.css’) 同时我们也需要一些loader来解析我们的css文件 npm i -D style-loader css-loader npm i -D less less-loader 配置文件:
module.exports = {
module:{
rules:[
{
test:/\.css$/,
use:['style-loader','css-loader']
},
{
test:/\.less$/,
use:['style-loader','css-loader','less-loader']
}
]
}
}
打包文 图片 url-loader 一般与file-loader搭配使用,功能与 file-loader 类似,如果文件小于限制的大小。则会返回 base64 编码,否则使用 file-loader 将文件移动到输出的目录中
前者用于处理小于8kb的图片,在编译图片过程中以代码显示,但是当图片大于8kb时,通过file-loader来加载, 此时在dist文件夹下生成了一个名字很长的图片,为了保证图片是被打包在dist下的,并且能保证原来的文件名,需要在webpack.config.js中配置以下代码 npm i -D url-loader npm i -D file-loader
{
test: /\.(png|jpg|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 13000,
name: 'img/[name].[hash:8].[ext]'
},
},
],
},
转义js npm i -D babel-loader @babel/preset-env @babel/core
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['es2015']
}
}
}
搭建本地服务器
安装 npm install webapck-dev-serve@2.9.1 --save–dev 配置webpack.config.js
devServer: {
contentBase: './dist',
inline: true
}
配置package.json
"scripts": {
"dev": "webpack-dev-server --open"
},
三、其他
- Babel的原理是什么?
babel 的转译过程也分为三个阶段,这三步具体是: 解析 Parse: 将代码解析?成抽象语法树(AST),即词法分析与语法分析的过程; 转换 Transform: 对于 AST 进?变换?系列的操作,babel 接受得到 AST 并通过 babel-traverse 对其进?遍历,在此过程中进?添加、更新及移除等操作; ?成 Generate: 将变换后的 AST 再转换为 JS 代码, 使?到的模块是 babel-generator
|