乐趣区

关于webpack:你需要知道的webpack高频面试题

谈谈你对 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
    }
}
退出移动版