关于webpack的一些配置?

webpack的基本配置

  • postcss-loader: 它负责进一步处理 CSS 文件,比如添加浏览器前缀,压缩 CSS 等。可以新建一个postcss.config.js文件单独定义postcss-loader配置
    详细描述地址
  • 处理图片
    在开发环境可使用本地图片,线上环境可比较小的图片可进行base64转换一下
module: {
       rules: [
           // 图片 - 考虑 base64 编码的情况
           {
               test: /\.(png|jpg|jpeg|gif)$/,
               use: {
                   loader: 'url-loader',
                   options: {
                       // 小于 5kb 的图片用 base64 格式产出
                       // 否则,依然延用 file-loader 的形式,产出 url 格式
                       limit: 5 * 1024,

                       // 打包到 img 目录下
                       outputPath: '/img1/',

                       // 设置图片的 cdn 地址(也可以统一在外面的 output 中设置,那将作用于所有静态资源)
                       // publicPath: 'http://cdn.abc.com'
                   }
               }
           },
       ]
   },

webpack如何配置多入口?

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { srcPath, distPath } = require('./paths')
module.exports = {
entry: {
       index: path.join(srcPath, 'index.js'),
       other: path.join(srcPath, 'other.js')
   },
 output: {
           // filename: 'bundle.[contentHash:8].js',  // 打包代码时,加上 hash 戳
           filename: '[name].[contentHash:8].js', // name 即多入口时 entry 的 key
           path: distPath,
           // publicPath: 'http://cdn.abc.com'  // 修改所有静态文件 url 的前缀(如 cdn 域名),这里暂时用不到
   },
},
plugins: [
       // new HtmlWebpackPlugin({
       //     template: path.join(srcPath, 'index.html'),
       //     filename: 'index.html'
       // })

       // 多入口 - 生成 index.html
       new HtmlWebpackPlugin({
           template: path.join(srcPath, 'index.html'),
           filename: 'index.html',
           // chunks 表示该页面要引用哪些 chunk (即上面的 index 和 other),默认全部引用
           chunks: ['index']  // 只引用 index.js
       }),
       // 多入口 - 生成 other.html
       new HtmlWebpackPlugin({
           template: path.join(srcPath, 'other.html'),
           filename: 'other.html',
           chunks: ['other']  // 只引用 other.js
       })
   ]
  • new CleanWebpackPlugin(), 每次打包会默认清空 output.path (dist)文件夹,在plugin中写

如何抽离压缩css文件

  • 生产环境下使用mini-css-extract-plugin插件,可以抽离css
  • 将抽离出来的css文件进行压缩使用terser-webpack-plugin(将css中的注释抽离)、optimize-css-assets-webpack-plugin(压缩css)
// webpack.prod.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const TerserJSPlugin = require('terser-webpack-plugin')
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
module export = {
module: {
       rules: [
           // 抽离 css
           {
               test: /\.css$/,
               loader: [
                   MiniCssExtractPlugin.loader,  // 注意,这里不再用 style-loader
                   'css-loader',
                   'postcss-loader'
               ]
           },
           // 抽离 less --> css
           {
               test: /\.less$/,
               loader: [
                   MiniCssExtractPlugin.loader,  // 注意,这里不再用 style-loader
                   'css-loader',
                   'less-loader',
                   'postcss-loader'
               ]
           }
       ]
   },
   plugins: [
       // 抽离 css 文件
       new MiniCssExtractPlugin({
           filename: 'css/main.[contentHash:8].css'
       })
   ],
   optimization: {
       // 压缩 css
       minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],
   }
}

1、webpack 如何抽离公共代码和第三方代码?

为什么要抽离公共代码和第三方代码?

  • 因为当多个组件引入同一个组件的时候,打包的时候都会再次去打包引入的那个组件,这就造成了浪费。同理,当多个组件引入第三方代码,那每次打包有多少个页面引入第三方过就会打包多少次,如果是很大的第三方代码就会造成页面加载慢。所以要抽离公共代码和第三方代码;
    直接上代码:
    在你的webpack.prod.js中使用splitChunks 分隔,
 optimization: {
        // 压缩 css
        minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],

        // 分割代码块
        splitChunks: {
            chunks: 'all',
            /**
             * initial 入口 chunk,对于异步导入的文件不处理
                async 异步 chunk,只对异步导入的文件处理
                all 全部 chunk
             */

            // 缓存分组
            cacheGroups: {
                // 第三方模块
                vendor: {
                    name: 'vendor', // chunk 名称
                    priority: 1, // 权限更高,优先抽离,重要!!!
                    test: /node_modules/,
                    minSize: 0,  // 大小限制
                    minChunks: 1  // 最少复用过几次
                },

                // 公共的模块
                common: {
                    name: 'common', // chunk 名称
                    priority: 0, // 优先级
                    minSize: 0,  // 公共模块的大小限制
                    minChunks: 2  // 公共模块最少复用过几次,就会将那个组件分配到common模块中缓存起来
                }
            }
        }
    }

webaopck.common.js

 plugins: [
        // new HtmlWebpackPlugin({
        //     template: path.join(srcPath, 'index.html'),
        //     filename: 'index.html'
        // })

        // 多入口 - 生成 index.html
        new HtmlWebpackPlugin({
            template: path.join(srcPath, 'index.html'),
            filename: 'index.html',
            // chunks 表示该页面要引用哪些 chunk (即上面的 index 和 other),默认全部引用
            chunks: ['index', 'vendor', 'common']  // 要考虑代码分割
        }),
        // 多入口 - 生成 other.html
        new HtmlWebpackPlugin({
            template: path.join(srcPath, 'other.html'),
            filename: 'other.html',
            chunks: ['other', 'common']  // 考虑代码分割
        })
    ]

webpack 如何实现异步加载js?

  • 使用import 包裹你的异步js文件,这是webpack里自带的,打包的时候默认将异步js文件单独打包
    在这里插入图片描述

webpack 如何处理JSX 和vue 文件?

JSX:

  • 可以去bable.js 里去查找我们的react ,安装 npm install --save-dev @babel/preset-react
  • 安装完成之后我们在.babelrc 文件这么配置
{
  "presets": ["@babel/preset-react"]
}

webpack 中的loader就是用bable-loader 就好了

module:{
rules:[
		{
                test: /\.js$/,
                loader: ['bable-loader'],
                 include: srcPath // src 目录下的所有文件
    	 },
	]
}

vue

  • 安装 vue-loader
    然后再装载器中写上我们的规则,.vue文件使用的vue-loader装载器
module:{
rules:[
		{
                test: /\.vue$/,
                loader: ['vue-loader'],
                 include: srcPath
    	 },
	]
}
  

module chunk bundle 的区别?

  • module 各个源码文件,webpack 中一切皆模块,src 下的js文件css文件等都是module
  • chunk 多模块合并成的,如entry impot() splitChunk
  • bundle 最终的输出文件,例如.js .css .png

webpack 的性能优化

  • 优化打包构建速度

    • 优化 babel-loader: 在 babel-loader后加cacheDirectory,加上这个之后,只要es6 代码没有改变第二次编译时就不会重新编译;第二个是明确编译范围,使用include ,一般在src下的文件。用于开发环境就可以了

    在这里插入图片描述

  • IgnorePlugin : 避免引入无用模块,直接不引入,代码中没有
    例如: moment 是时间的插件,安装之后有很多的语言文件,使用IgnorePlugin 就可做到只引入中文。代码如下
plugins:[
 new webpack.IgnorePlugin(/\.\/local/,/moment/) // 打包的时候忽略local文件的内容
]

如果想引入中文就要手动引入中文包,代码如下

import moment from 'moment'
import 'moment/local/zh-cn' 

moment.loacl('zh-cn')
moment.format('YYYY-MM')

  • noParse 避免重复打包,就是我们代码中引入了那种xx.main.js 的文件,这些都是别人已经打包处理过了,所以我们不需要再打包一遍,就可使用noParse。引入不打包

在这里插入图片描述

  • happyPack 多进程打包,可在开发环境和生产环境下使用
    • js单进程,开启多进程打包
    • 提高构建速度,(特别是多核CPU)
const { srcPath, distPath } = require('./paths')
const happyPack = require('happypack')
 
 module:{
   rules:[
		// js 之前是bable-loader,使用happypack之后就得改成如下
		{
			test:/\.js$/,
			// 把对js文件的处理转交给id为babel的HappPack 实例处理
			use:['happypack/loader?id=babel'],
			include:srcPath
			// exclude:/node_modules/
		}
  ]
 },
 plugins:[
	// happypack 开启多进程打包
	new HappyPack({
		// 用唯一的标识付id来代表当前的HappyPack 是用来处理一类特定的文件
		id:'babel',
		// 如何处理.js 文件,用法和loader 配置中国的一样
		loaders:['babel-loader?cacheDirectory']
	})
]
  • ParallelUglifyPlugin 多进程压缩js,只能放在生产环境下
    • webpack 内置的Uglify 工具压缩JS
    • JS单线程,开启多进程压缩更快
    • 和happyPack 同理
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin')
plugins:[
  new ParallelUglifyPlugin({
     // 传递给UGLIFYjs 的参数
     // 还是使用UglifuJS压缩,只不过帮厨开启了多线程
     uglifyJS:{
			output:{
 				beautify:false,// 最紧凑的输出
 				comments:false,// 删除所有的注释
 			},
 			compress:{
 				deop_console:true, // 删除所有的console语句,可以兼容ie浏览器
 				collapse_vars:true,// 内嵌定义了但是只用到一次的变量
 				reduce_vars:true // 提取出出现多次但是没有定义成变量去引用的静态值
			}
      }
  
  })
  
]

  • 关于开启多进程
    • 项目较大,打包较慢,开启多进程能提高速度
    • 但是如果项目较小,打包很快,开启多进程会降低速度(进程开销)
    • 按需使用
  • 我们代码改完之后,浏览器就自动刷新,但是一般不会去自己配置这个,因为你只要配置了devServer就自带的有代码更新自动刷新的功能
    在这里插入图片描述
  • 如何配置热更新
    • 自动刷新:整个网页全部刷新,速度较慢,状态会丢失,
    • 热更新:新代码生效,网页不刷新,状态不丢失,路由不丢失,对于css 直接开启devServer 即可,但是js文件就不行了,只能用于开发环境,如果你要去生产环境的话,就得把那些代码删掉
    • 需要你额外去处理那些模块需要热更新然后调用一个回调,就成本来挺大,如果你的项目不是很大,网页刷新对你开发没啥影响也可以不用开启热更新
      webapck 配置代码如下:
cost HotModuleReplacementPlugin  =  require('webpack/lib/HotModuleReplacementPlugin')

entry:{
// 不用hot是这样子的 index:path.join(srcPath,'index.js')
// 使用热更新之后要这么写
index:[
	'webpack-dev-server/client?http://loaclhost:8080/',
	'webpack/hot/dev-server',
	path.join(srcPath,'index.js')
 ]

},
olugins:[
	new HotModuleReplacementPlugin()
],

devServer:{
 // 此处省略很多配置
 hot:true
 }

** 需要热更新的JS模块**

import {sum} from './math'

// 开启热更新之后的代码
if(module.hot){
	module.hot.accept(['./math'],()=>{
	const sumRes = sum(10,20)
 })
}
  • DllPlugin 动态链接库
    • 前端框架如vue react 体积大,构建慢
    • 比较稳定,不常升级版本
    • 同一个版本只构建一次即可,不用每次都重新构建
    • webpack 以内置DllPlugin 支持,不需要我们自己去下载
    • DllPlugin插件 - 打包出dll文件(我们可以先把vue或react 进行预打包一遍)
    • DllReferencePlugin 插件 - 使用dll文件
    • 配置之后对代码的引入没有任何修改

(1): 单独对需要使用DllPlugin的框架创建一个文件webpack.dll.js

const path = require('path')
const DllPlugin = require('webpack/lib/DllPlugin')
const { srcPath, distPath } = require('./paths')

module.exports = {
  mode: 'development',
  // JS 执行入口文件
  entry: {
    // 把 React 相关模块的放到一个单独的动态链接库
    react: ['react', 'react-dom']
  },
  output: {
    // 输出的动态链接库的文件名称,[name] 代表当前动态链接库的名称,
    // 也就是 entry 中配置的 react 和 polyfill
    filename: '[name].dll.js',
    // 输出的文件都放到 dist 目录下
    path: distPath,
    // 存放动态链接库的全局变量名称,例如对应 react 来说就是 _dll_react
    // 之所以在前面加上 _dll_ 是为了防止全局变量冲突
    library: '_dll_[name]',
  },
  plugins: [
    // 接入 DllPlugin
    new DllPlugin({
      // 动态链接库的全局变量名称,需要和 output.library 中保持一致
      // 该字段的值也就是输出的 manifest.json 文件 中 name 字段的值
      // 例如 react.manifest.json 中就有 "name": "_dll_react"
      name: '_dll_[name]',
      // 描述动态链接库的 manifest.json 文件输出时的文件名称
      path: path.join(distPath, '[name].manifest.json'),
    }),
  ],
}

(2):然后在package.json中配置运行命令

 "scripts": {
    "dev": "webpack serve --config build/webpack.dev.js",
    "dll": "webpack --config build/webpack.dll.js"
  },

(3): 运行命令,npm run dll 会打包出两个文件:
react.dll.js, react.manifest.json
(4):然后在index.html中引入react.dll.js

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <div id="root"></div>
    <script src="./react.dll.js"></script>
</body>
</html>

(5):在webpack.dev.js 文件中引入DllReferencePlugin,并使用

// 第一,引入 DllReferencePlugin
const DllReferencePlugin = require('webpack/lib/DllReferencePlugin');

module.exports = merge(webpackCommonConf, {
    mode: 'development',
    module: {
        rules: [
            {
                test: /\.js$/,
                use: ['babel-loader'],
                include: srcPath,
                exclude: /node_modules/ // 第二,不要再转换 node_modules 的代码
            },
        ]
    },
    plugins: [
        new webpack.DefinePlugin({
            // window.ENV = 'production'
            ENV: JSON.stringify('development')
        }),
        // 第三,告诉 Webpack 使用了哪些动态链接库
        new DllReferencePlugin({
            // 描述 react 动态链接库的文件内容
            manifest: require(path.join(distPath, 'react.manifest.json')),
        }),
    ],
    
})

(6)、就可以去引入react 了,构建块

webpack 优化产出代码

* 打包体积更小,加载就快
* 合理分包,不重复加载(比如多个入口很重复的代码,他能合理的分包,把重复的逻辑分出来,就可以相互引用,而不是像复制黏贴一样的去打包,这会让我们的代码加载的更快,体积更小,逻辑更合理)
* 执行速度更快,内存使用更少

(1)、小图片base64 编码
在这里插入图片描述
(2)、bundle 加hash
在这里插入图片描述
(3)、懒加载
(4)、提取公共代码
在这里插入图片描述
(5)、IngorePlugin: 避免引入无用模块,直接不引入,代码中没有
(6)、使用cdn加速
第一步,在webpack中配置cnd的地址,publicPath 修改多有静态文件url 的前缀
第二步,把打包之后的文件上传到cdn去,比如css文件和js文件

在这里插入图片描述
或者一些图片

在这里插入图片描述

(7)、使用production ,自动压缩代码,在生产环境下使用
- 自动开启压缩代码
- vue React 在produnction 环境下的话会自动删掉调试代码(如开发环境的warning ),让体积更小一些
- 启用tree-shaking (过滤掉无用的代码)

(8)、Scope Hosting

  • 代码体积更小,压缩之后的代码会将两个文件里的代码合并成一个函数,没有使用这个的话,会将每个文件创建一个函数,就会出现代码很多很乱
  • 创建函数作用域更少
  • 代码可读性更好

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
**使用scope hosting **
在这里插入图片描述

使用production好处?

  • 自动压缩代码
  • vue react等会自动删掉调试代码
  • 启动tree-shaking

什么是Tree-Shaking (过滤掉没有调用到的代码)

webpack4有这个功能,很弱,只支持当前js文件中无用的代码;webpack5加强了这个功能。但是只会在生产模式下才会过滤,开发模式都会打包。
注意: ES6 module 才能让tree-shaking生效,使用commonjs 就不行

ES6 module 和Commonjs 的区别

  • es6 Module 静态引入,编译时引入
  • Commonjs 是动态引入,执行时引入
  • 只有es6 module 才能静态分析,实现tree-shaking
    在这里插入图片描述

babel

  • 前端开发环境必备工具
  • 同webpack ,需要了解基本的配置和使用

1、babel 环境搭建和基本配置

babel解决 语法层面的问题。用于将ES6+的高级语法转为ES5。而要解决 API层面的问题,如Map、Proxy、Reflect、Symbol、Promise等api,是不能转换的,所以需要polyfill 来解决。常见的有 babel-polyfill、 babel-runtime 和 babel-plugin-transform-runtime。

2、babel -polyfill

  • 优点: 一次性解决所有兼容性问题,而且是全局的,浏览器的console也可以使用
  • 缺点:
    • 一次性引入了ES6+的所有polyfill, 打包后的js文件体积会偏大
    • 对于现代的浏览器,有些不需要polyfill,造成流量浪费
    • 污染了全局对象
    • 适合框架或库的开发

3、babel-runtime

  • 它将开发者依赖的全局内置对象等,抽取成单独的模块,并通过模块导入的方式引入,避免了对全局作用域的修改(污染)。
  • 缺点: 每个模块内单独引用和定义polyfill函数,造成了重复定义,使代码产生冗余

4、babel-plugin-transform-runtime

  • 优点:
    • 无全局污染
    • 依赖统一按需引入(polyfill是各个模块共享的), 无重复引入, 无多余引入
    • 适合用来编写lib(第三方库)类型的代码
  • 缺点:
    • 被polyfill的对象是临时构造并被import/require的,并不是真正挂载到全局
    • 由于不是全局生效, 对于实例化对象的方法,如[].include(x), 依赖于Array.prototype.include仍无法使用

前端为何要进行打包和构建?

代码层面讲:

  • 体积更小(tree-shaking,压缩,合并),加载更快
  • 编译高级语言或语法(TS、ES6+,模块化、scss等)
  • 兼容性和错误提示(Polyfill、postcss 、eslint)
    团队效率方面:
  • 统一、高效的开发环境
  • 统一的构建流程和产出标准
  • 集成公司构建规范(提测、上线等)

loader 和plugin 的区别

  • loader模块转换器,如less->css,es6->es5
  • plugin扩展插件,如 HtmlWebpackPlugin ,html 打包进dist文件夹里去

常见的loder 和 plugin 的有哪些?

loader链接
plugins 链接

babel 和webpack 的区别

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

如何产出一个lib

在这里插入图片描述

babel-polyfill 和babel-runtime 的区别

  • babel-polyfill 会污染全局
  • babel-runtime 不会污染全局
  • 产出第三方的lib 要用babel-runtime

webpack 如何实现懒加载

  • import
  • 结合vue react 异步组件
  • 结合vue-router react-router 异步加载路由

为何Proxy 不能被Polfyill

  • 如class 可以用function 模拟
  • 如promise 可以用callback 来模拟
  • 但是Proxy 的功能用Object.defineProperty 无法模拟
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值