谈谈你对 webpack 的认识
webpack 是一个模块打包工具,能够应用它治理我的项目中的模块依赖,并编译输出模块所需的动态文件。它能够很好地治理、打包开发中所用到的 HTML,CSS,JavaScript 和动态文件(图片,字体)等,让开发更高效。对于不同类型的依赖,webpack 有对应的模块加载器,而且会剖析模块间的依赖关系,最初合并生成优化的动态资源。
webpack 的基本功能和工作原理?
- 代码转换:TypeScript 编译成 JavaScript、SCSS 编译成 CSS 等等
- 文件优化:压缩 JavaScript、CSS、HTML 代码,压缩合并图片等
- 代码宰割:提取多个页面的公共代码、提取首屏不须要执行局部的代码让其异步加载
- 模块合并:在采纳模块化的我的项目有很多模块和文件,须要构建性能把模块分类合并成一个文件
- 主动刷新:监听本地源代码的变动,主动构建,刷新浏览器
- 代码校验:在代码被提交到仓库前须要检测代码是否符合规范,以及单元测试是否通过
- 主动公布:更新完代码后,主动构建出线上公布代码并传输给公布零碎。
webpack 构建过程
- 从 entry 里配置的 module 开始递归解析 entry 依赖的所有 module
- 每找到一个 module,就会依据配置的 loader 去找对应的转换规则
- 对 module 进行转换后,再解析出以后 module 依赖的 module
- 这些模块会以 entry 为单位分组,一个 entry 和其所有依赖的 module 被分到一个组 Chunk
- 最初 webpack 会把所有 Chunk 转换成文件输入
- 在整个流程中 webpack 会在失当的机会执行 plugin 里定义的逻辑
webpack 打包原理
将所有依赖打包成一个 bundle.js,通过代码宰割成单元片段按需加载
什么是 webpack,与 gulp,grunt 有什么区别
- webpack 是一个模块打包工具,能够递归地打包我的项目中的所有模块,最终生成几个打包后的文件。
- 区别:webpack 反对代码宰割,模块化(AMD,CommonJ,ES2015),全局剖析
什么是 entry,output?
- entry 入口,通知 webpack 要应用哪个模块作为构建我的项目的终点,默认为./src/index.js
- output 进口,通知 webpack 在哪里输入它打包好的代码以及如何命名,默认为./dist
什么是 loader,plugins?
- loader 是用来通知 webpack 如何转换某一类型的文件,并且引入到打包出的文件中。
- plugins(插件) 作用更大,能够打包优化,资源管理和注入环境变量
什么是 bundle,chunk,module?
bundle 是 webpack 打包进去的文件,chunk 是 webpack 在进行模块的依赖剖析的时候,代码宰割进去的代码块。module 是开发中的单个模块
如何主动生成 webpack 配置?
能够用一些官网脚手架
- webpack-cli
- vue-cli
// 首先装置
npm install -g @vue/cli
// 新建我的项目 hello
vue create hello
- nuxt-cli
// 确保装置了 npx,npx 在 npm5.2.0 默认装置了
// 新建我的项目 hello
npx create-nuxt-app hello
webpack 如何配置单页面和多页面的应用程序?
- 单个页面
module.exports = {entry: './path/to/my/entry/file.js'}
- 多页面应用程序
module.entrys = {
entry: {
pageOne: './src/pageOne/index.js',
pageTwo: './src/pageTwo/index.js'
}
}
webpack-dev-server 和 http 服务器如 nginx 有什么区别?
webpack-dev-server 应用内存来存储 webpack 开发环境下的打包文件,并且能够应用模块热更新,相比传统 http 服务器开发更加简略高效,webpack 视频解说:进入学习
什么是模块热更新?
webpack 的一个性能,能够使代码批改后不必刷新浏览器就自动更新,高级版的主动刷新浏览器
dev-server 是怎么跑起来的
webpack-dev-server 反对两种模式来主动刷新页面
- iframe 模式(页面放在 iframe 中,当发送扭转时重载)
无需额定配置,只有以这种格局 url 拜访即可。http://localhost:8080/webpack-dev-server/index.html
- inline 模式(将 webpack-dev-server 的客户端入口增加到 bundle 中)
inline 模式下 url 不必发生变化,但启动 inline 模式分两种状况
// 以命令行启动 webpack-dev-server 有两种形式 // 形式 1 在命令行中增加 --inline 命令 // 形式 2 在 webpack-config.js 增加 devServer:{inline: true}// 以 node.js API 启动有两种形式 // 形式 1 增加 webpack-dev-server/client?http://localhost:8080/ 到 webpack 配置的 entry 入口点
config.entry.app.unshift("webpack-dev-server/client?http://localhost:8080/");
// 将 <script src="http://localhost:8080/webpack-dev-server.js"></script> 增加到 html 文件中
应用过 webpack 外面哪些 plugin 和 loader
loader
- babel-loader: 将 ES6+ 转移成 ES5-
- css-loader,style-loader:解析 css 文件,可能解释 @import url() 等
- file-loader:间接输入文件,把构建后的文件门路返回,能够解决很多类型的文件
- url-loader:打包图片
// url-loader 增强版的 file-loader,小于 limit 的转为 Base64, 大于 limit 的调用 file-loader
npm install url-loader -D
// 应用
module.exports = {
module: {
rules: [{test: /\.(png|jpg|gif)$/,
use: [{
loader: 'url-loader',
options: {
outputPath: 'images/',
limit: 500 // 小于 500B 的文件打包出 Base64 格局,写入 JS
}
}]
}]
}
}
plugins
- html-webpack-plugin: 压缩 html
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
//...
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html', // 配置输入文件名和门路
template: './public/index.html', // 配置要被编译的 html 文件
hash: true,
// 压缩 => production 模式应用
minify: {
removeAttributeQuotes: true, // 删除双引号
collapseWhitespace: true // 折叠 html 为一行
}
})
]
}
- clean-webpack-plugin: 打包器清理源目录文件,在 webpack 打包器清理 dist 目录
npm install clean-webpack-plugin -D
// 批改 webpack.config.js
const cleanWebpackPlugin=require('clean-webpack-plugin')
module.exports = {plugins: [new cleanWebpackPlugin(['dist'])]
}
webpack 中 babel 的实现
装置 npm i -D @babel-preset-env @babel-core babel-loader
- @babel-preset-env:能够让咱们灵便设置代码指标执行环境
- @babel-core: babel 外围库
- babel-loader: webpack 的 babel 插件,让咱们能够在 webpack 中运行 babel
配置.babelrc
{"presets": ['@babel/preset-env']
}
配置 webpack.config.js
module.exports = {
entry: './src/index.js',
output: {path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
use: {loader: 'babel-loader'}
}]
}
}
提取专用代码
module.exports = {
optimization: {
splitChunks: {
common: {
// 抽离公共代码
chunks: 'initial',
name: 'common', // 打包后的文件名
minChunks: 2, // 最小援用 2 次
minSize: 0 // 超出 0 字节就生成一个新包
},
styles: {
// 抽离专用代码
name: 'styles',
test: /\.css$/,
chunks: 'all',
minChunks: 2,
enforce: true
},
vender: {
// 抽离第三方插件
test: /node_modules/,
chunks: 'initial',
name: 'vendor', // 打包后的文件名
priority: 10 // 设置优先级,避免与自定义公共代码提取时被笼罩,不进行打包
}
}
}
}
什么是长缓存?在 webpack 中如何做到长缓存优化?
- 浏览器在用户拜访页面的时候,为了放慢加载速度会对用户拜访的动态资源进行存储,然而每一次代码降级或更新都须要浏览器下载新的代码,最简略不便的形式就是引入新的文件名称。
- webpack 中能够在 output 中指定 chunkhash,并且拆散常常更新的代码和框架代码。通过 NameModulesPlugin 或 HashedModuleIdsPlugin 使再次打包文件名不变。
什么是 Tree-shaking?CSS 能够 Tree-shaking?
Tree-shaking 是指在打包中取出那些引入了但在代码中没有被用到的死代码。webpack 中通过 uglifysPlugin 来 Tree-shaking JS。CSS 须要应用 purify-CSS
继承 8 种
原型链继承
- 重点:子的原型对象为 new 一个父的实例
Child.prototype = new Parent();
- 毛病:多个实例对援用类型的操作会被篡改
借用构造函数继承
- 重点:在子构造函数外部调用父构造函数
Parent.call(this)
- 毛病:无奈实现复用,不能继承原型属性 / 办法
组合继承
- 重点:应用原型链继承共享的属性和办法,通过借用构造函数继承实例属性
function Child(name,age){
// 继承属性
Parent.call(this, name)
this.age=age
}
// 继承办法
Child.prototype = new Parent()
Child.prototype.constructor = Child;
- 毛病:无论在什么状况都会调用两次父构造函数,一次是创立子类型原型,另一次是在子构造函数外部
原型式继承
- 重点:执行对给定对象的浅复制
function object(obj){function F(){}
F.prototype=obj return new F();}
var person1=object(person);
在 ES5 中 Object.create() 可替换下面的办法 object() var person1 = Object.create(person);
- 毛病:原型链继承多个实例的援用类型属性指向雷同,存在篡改的可能;无奈传递参数
寄生式继承
- 重点:在原型式继承的根底上,加强对象,返回构造函数
function createAnother(obj){var clone=object(obj);
// ES5 中用这个
// var clone=Object.create(obj);
// 加强对象
clone.sayHi=function(){};
return clone;
}
var person1=createAnother(person)
- 毛病:同原型式继承
寄生组合式继承
- 重点:联合构造函数传递参数和寄生模式实现继承
// 借用构造函数增强子类实例属性(反对传参和防止篡改)function Child(name,age){
// 继承属性
Parent.call(this, name)
this.age=age
}
function inheritPrototype(Child, Parent){var prototype=Object.create(Parent.prototype);
prototype.constructor=Child;
Child.prototype=prototype;
}
// 将父类原型指向子类,这样子类就能应用父类原型链的属性 / 办法
inheritPrototype(Child, Parent);
长处:只调用一次构造函数,原型链不变,是最成熟的
混入形式继承多个形式
重点:利用 Object.assign 将父类原型上的办法拷贝到子类原型上,这样子类实例实例就能够应用父类的办法
Object.assign(Child.prototype, Parent.prototype);
Child.prototype.constructor=Child;
ES6 类 extends
重点:应用 extends 表明继承自哪个父类,并且在子类构造函数中必须应用 super,能够看做是 Parent.call(this,value)
class Parent{constructor(value){this.val=value}
}
class Child extends Parent{constructor(value){super(value)
this.val = value
}
}