webpack和Babel面试题

1、前端代码为什么要进行构建和打包?

代码层面:

  • 可以使代码体积更小(tree-shaking,压缩,合并),加载更快
  • 可以编译高级语言或语法(TS,ES6+,模块化,scss)
  • 可以检查错误及实现兼容性(polyfill,postcss,eslint)

开发流程层面:

  • 可以统一高效的开发环境
  • 可以统一构建流程和产出标准
  • 可以集成公司的构建规范(提测,上线)

2、webpack的一些核心概念?

  • entry:入口,指示webpack应该使用哪个模块来作为构建其内部依赖图的开始
  • output:输出结果,告诉webpack在哪里输出它所创建的bundle,以及如何命名这些文件
  • module:webpack里一切皆模块,一个模块对应一个文件,webpack会从配置的entry开始递归找出所有依赖的模块
  • chunk:代码块,一个chunk由多个模块组合而成,用于代码合并与分割。
  • loader:模块转换器,让webpack能够去处理js,json以外的其他类型文件,并将他们转化为有效模块
  • plugin:扩展插件,在webpack运行生命周期会广播出许多事件,plugin可以监听这些事件,在合适的时机通过webpack提供的API改变输出结果。例如打包优化,资源管理
  • mode:模式,告知webpack使用相应模式的内置优化

3、loader和plugin的区别是什么?常见的loader和plugin有哪些?

  • loader:模块转化器,例如less-loader可以将less转化成css。ts-loader,babel-loader,file-loader等
  • plugin:扩展插件,例如 html-webpack-plugin生成html文件,例如clean-webpack-plugin删除output.path中文件,mini-css-extract-plugin抽离css, hot-module-replacement-plugin配置热更新splitChunksPlugin进行代码分割等。
  • loader运行在打包文件之前,plugins在整个编译周期都会起作用

4、webpack和Babel有什么区别?

  • Babel是js新语法编译工具,不关心模块化
  • webpack是打包构建工具,是多个loader和plugin的集合

5、webpack常见的性能优化有哪些?

  • 优化babel-loader
  • 使用ignorePlugin
  • 使用noparse
  • 使用happyPack多进程打包
  • 使用parallelUglifyPlugin多进程压缩
  • 自动刷新/热更新 (开发环境)
  • DllPlugin (开发环境)
  • 小图片base64编码
  • bundle加hash
  • 懒加载
  • 提取公共代码(splitChunk)
  • IgnorePlugin
  • 使用production
  • 使用scope Hoisting

6、如何产出一个lib?

output:{
    // lib的文件名
    filename:'lodash.js',
    // 输出lib到dist目录下
    path:distPath,
    // lib的全局变量名
    library:'lodash'
}

7、webpack如何抽离并压缩css文件?

通过MiniCssExtractPlugin.loader(不再用style-loader)

plugins选项中:

plugins:[
     new CleanWebpackPlugin(), // 每次都清空output.path 文件夹
     new MiniCssExtractPlugin({
          filename: 'static/css/[name].[contenthash:8].css',
          chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
     }),

]

optimization选项中:

optimization:{
   minimizer:[
        new TerserPlugin({}),
        new CssMinimizerPlugin(),
   ]
}

8、webpack如何配置多入口?

entry里配置多个入口

entry:{
    index:path.join(srcPath,'index.js'),
    other:path.join(srcPath,'other.js')
}

output: name变量区分多入口

output:{
    filename:'[name].[contentHash:8].js',
    path:distPath
}

plugins: 配置多入口

plugins:[
    new HtmlWebpackPlugin({
        template:path.join(srcPath,'index.html'),
        filename:'index.html',
        chunks:['index']. // 只引用index.js
    }),
    new HtmlWebpackPlugin({
        template:path.join(srcPath,'other.html'),
        filename:'other.html',
        chunks:['other'].  // 只引用other.js
    }) 
]

9、webpack如何懒加载?

import('./danamic.js').then(res=>{

})
// 会返回一个promise

10、webpack如何处理jsx和vue?

react使用@babel/preset-react. + babel-loader

vue则使用vue-loader

11、module,chunk,bundle分别是什么,有什么区别?

module:各个源码文件,webpack中一切皆模块,能被import或者export的js,css,图片

chunk:多模块合并成的,还在内存中没产出的。当module源文件传到webpack打包时,webpack会根据文件引用关系生成chunk文件,webpack会对chunk文件进行一些操作

bundle: 最终的输出文件。webpack处理好chunk文件后,最终会输出bundle文件,这个bundle文件包含了经过加载和编译的最终源文件,所以它可以直接在浏览器中运行。

12、webpack优化构建速度的方式

  • 优化babel-loader: ①开启缓存 ② 明确范围
  • {
        test:/\.js$/,
        use:['babel-loader?cacheDirectory'], // 开启缓存
        include:path.resolve(__dirname,'src'), // 明确范围
        exclude:path.resolve(__dirname,'node_modules') // 二者选其一即可
    }
  • 使用ignorePlugin 避免引入无用模块  (直接不引入,代码中没有)
  • 使用noParse避免重复打包。(例如 XXX.min.js) (引入但不打包)
  • 使用happyPack多进程打包
  • 使用ParallelUglifyPlugin多进程压缩js
  • 使用HotModuleReplacementPlugin开启热更新(仅开发环境)
  • 使用DllPlugin动态链接库插件 (仅开发环境)

13、happyPack是什么?

多进程打包。提升打包速度。

{
    test:/\.js$/,
    use:['happypack/loader?id=babel'], 
    include:path.resolve(__dirname,'src'), 
}
new HappyPack({
    id:'babel',
    loaders:['babel-loader?cacheDirectory']
})

14、ParallelUglifyPlugin是什么?

多进程压缩输出js代码

new ParallelUglifyPlugin({
    uglifyJS:{
        output:{
            beautify:false, // 最紧凑的输出
            comments:false, //删除所有注释
        },
        compress:{
            drop_console:true, 
            collapse_vars: true,
        }
    }
})

15、webpack如何配置热更新?

自动刷新:保存了代码之后,整个网页全部刷新,状态会丢失

热更新:新代码生效,但网页不刷新,状态不丢失

配置了devSever选项后,默认就会开启自动刷新。

const HotModuleReplacementPlugin = require('webpack/lib/HotModuleReplacementPlugin')

module.exports = merge(webpackCommonConfig,{
    mode:'development',
    entry:{
        index:[
            'webpack-dev-server/client?http://localhost:8080',
            'webpack/hot/dev-server',
            path.join(srcPath,'index.js')
        ],
    },
    module:{
        rules:[
            {
              test:/\.js$/,
              loader:['babel-loader?cacheDirectory'],
              include:srcPath
            }
        ]
    },
    plugins:[
        new webpack.DefinePlugin({
            ENV:JSON.stringify('development')
        }),
        new HotModuleReplacementPlugin(), //. ------配置热更新插件
    
    ],
    devServer:{
        port:8080,
        progress:true,//显示打包进度条
        contentBase:distPath, //根目录
        open:true,//自动打开浏览器
        compress:true, // 开启gzip压缩
        hot:true, // -----------开启热更新
        proxy:{ // 配置代理
            /**********将本地/api/xxx代理到 localhost:3000/api/xxx **/
           '/api':'http://localhost:3000',
            /*****将本地的 /api2/xxx代理到 localhost:3000/xxx. ***/
            '/api2':{
                target:'http://localhost:3000'
            }
        }
    }
})

16、什么是DllPlugin?

前端框架如Vue,React项目体积大,构建慢;但是他们的版本比较稳定,不常升级。使用DllPlugin则同一个版本只需构建一次即可,不用每次都重新构建。

webpack已经内置了DllPlugin

DllPlugin -- 打包出dll文件

DllReferencePlugin -- 使用dll文件

17、webpack性能优化产出代码的方式

体积更小;合理分包,不重复加载;速度更快,内存使用更小

①小图片base64

{
    test:/\.(png|jpg|jpeg|gif)$/,
    use:{
        loader:'url-loader',
        options:{
            // 小于5kb的图片用base64格式产出,否则依然用file-loader的形式产出URL格式
            limit: 5 * 1024, 
            outputPath:'/img1/'
        }
    }
}

②bundle加hash

根据文件的内容算出一个8位的hash值,文件内容发生变化,hash值就会变,hash值不变则会命中缓存

filename:'[name].[contentHash:8].js'

③懒加载

④使用mode:'production' 打包代码 (会自动压缩代码,vue,react会自动删掉调试代码,会自动启用tree-shaking)

18、什么是tree-shaking?

  • 在打包时移除掉javascript上下文中无用的代码,从而优化打包结果。
  • ES Module才能让tree-shaking生效,commonjs不行。

19、ES6 Module和CommonJs的区别?

  • ES6 Module静态引入,编译时引入
  • CommonJs动态引入,执行时引入
  • 只有ES6 Module才能静态分析,实现tree-shaking.

20、什么是scopeHoisting?

  • 默认情况下,经过webpack打包后的模块资源会被组织成一个个函数形式,这种结构会导致大量作用于包裹代码,从而导致体积增大;运行代码时创建的函数作用域变多,内存开销变大。
  • scope hoisting将符合条件的多个模块合并到同一个函数空间内,从而使打包出来的代码体积更小,内存开销也随之变小。
  • 原理:分析出模块之间的依赖关系,将打散的模块合并到一个函数中。
  • 由于scopeHoisting需要分析出模块之间的依赖关系,因此要采用ES6模块化语句。
  • 自动启用:mode设置为production
  • 手动启用: 配置ModuleConcatenationPlugin插件
    const ModuleConcatenationPlugin = require('webpack/lib/optimize/ModuleConcatentionPlugin')
    
    module.exports = {
        resolve:{
        // 针对 npm中的第三方模块优先采用jsnext:main中指向的ES6模块化语法的文件
        mainFields:['jsnext:main','browser','main']
        },
        plugins:[
            new ModuleConcatentationPlugin()
        ]
    }

21、babel什么作用?babel-polyfill是什么?

用于将ES6+语法编写的代码转换为向后兼容的js语法,以便能够运行在当前或旧版本的浏览器或者其他环境中。

babel-polyfill是polyfill和core.js/regenerator的集合,但是在Babel7.4以后被弃用。推荐直接使用core.js(集成了ES6+语法的补丁)和regenerator。

22、什么是babel-runtime?

引入babel-polyfill会有一定副作用,例如引入新的全局对象,比如Promise,WeakMap等;或者是修改了现有的全局对象,例如修改了Array、String等的原型链。在引用开发中影响不大,但如果是在开发库、工具时引入polyfill,则会有潜在问题。

babel-runtime,将开发者依赖的全局内置对象,抽取成单独的模块,并通过模块导入的方式引入,避免了对全局作用域的修改。因此如果是开发工具和库,可以使用babel-runtime.

23、babel-polyfill和Babel- runtime有什么区别?

babel-polyfill会污染全局,Babel- runtime不会污染全局,如果是产出第三方lib要用babel-runtime

24、为什么proxy不能被polyfill?

proxy功能无法用Object.defineProperty模拟,

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值