webpack简单配置及其用法二

一、编写可维护的webpack构建配置

栗子:构建配置包设计

构建配置抽离成npm包的意义

通过性:业务开发者无需关注构建配置;统一团队构建脚本

可维护性:构建配置合理的拆分;reademe,changelog文档

质量:冒烟测试,单元测试,测试覆盖率;持续继承

构建配置管理的可选方案

1)通过多个配置文件管理不同环境的构建,webpack --config参数进行控制使用的配置文件,如

基础配置:webpack.base.js;开发环境:webpack.dev.js;生产环境:webpack.prod.js;ssr环境:webpack.ssr.js

2)将构建配置设计成一个库,比如hjs-webpack  Neutrino      webpack-blocks

扫描二维码关注公众号,回复: 12803829 查看本文章

规范:git commit日志,README,ESLINT规范,Semver规范

质量:冒烟测试,单元测试,测试覆盖率和CI

3)抽成一个工具进行管理,比如:create-react-app   kyt  nwb

4)将所有的配置写在一个文件,通过--env参数控制分支选择、

1)2)适合小团队使用,大团队可选择3)方式

通过webpack-merge组合配置

const merge = require("webpack-merge)
merge(
    {a:[1], b:5, c:20},
    {a:[2], b:6, d:35}
)
>{a:[1,2],b:6,c:20,d:35} // 非对象或非数组,则有相同的变量名,后面的覆盖前面的
合并配置:module.exports=merge(baseConfig,devConfig)

二、webpack构建速度和体积优化策略

体积优化方法:

1)scope hoisting

2)tree-shaking

3)公共资源分离

4)图片压缩

5)动态polyfill

提升构建速度方法:

1)充分使用缓存,提升二次构建速度

2)进一步分包:预编译资源模块

栗子:构建速度和速度分析

1)使用webpack内置的stats:构建的统计信息

2)速度分析:用speed-measure-webpack-plugin,分析整个打包的耗时,每个插件和loader的耗时

安装插件

npm install -D speed-measure-webpack-plugin

创建对象

const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");

const smp = new SpeedMeasurePlugin();

将之前module.exports的内容,包裹在smp.wrap()里面

smp.wrap(...)

3)体积分析:用webpack-bundle-analyzer

可以分析依赖的第三方模块文件大小,业务里面的组件代码大小

安装依赖

npm install -D webpack-bundle-analyzer

配置

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;

module.exports = {
  plugins: [
    new BundleAnalyzerPlugin()
  ]
}

栗子:使用高版本的webpack和node

栗子:充分利用缓存,提升二次构建速度----首次构建速度不会变化,下次构建的速度才会有变化

缓存思路:

1)babel-loader开启缓存,解析js语法或者jsx语法,等下次在解析一样的语法的时候,就可以读取缓存的内容,提升解析的速度

2)terser-webpack-plugin 开启缓存,代码压缩的时候,提升压缩速度

3)cache-loader或者hard-source-webpack-plugin,提升模块转换阶段的速度

如果在代码层面开启了缓存,那在node_modules下有.cache目录,比如开启了babel-loader,则会生成文件夹babel-loader(node_modules/.cache/babel-loader/....),文件夹里面包含了解析出的js文件

注意:如果开启了缓存,有可能会影响到包的更新,比如在项目中安装了包[email protected],后面更新成[email protected],但是发现这个包的代码还是上个版本的

解决方法:就是在更新包之前要将.cache文件夹整个移除,在更新包

以hard-source-webpack-plugin为栗子:

1)安装hard-source-webpack-plugin插件

npm install -D hard-source-webpack-plugin

2)在配置文件中,引进该插件,并进行配置

const HardSourceWebpackPlugin = require('hard-source-webpack-plugin')



plugin: [
  new HardSourceWebpackPlugin()
]

栗子:缩小构建目标

目的:尽可能的少构建模块,

比如:babel-loader不解析node_modules

module.exports = {
    module: {
        rules: [
            {
                test: /\.js$/,
                loader: ''babel-loader,
                exclude: 'node_modules
            }
        ]
    }
}

比如:减少文件搜索范围:

webpack同node查找文件的方法很相似,指定要查找的路径或者文件类型,缩小查找时间

优化resolve.modules配置(减少模块搜索层级)

优化resolve.mainFields配置

优化resolve.extensions配置

合理使用alias

resolve: {
    alias: {
        react: path.resolve(__dirname, ./node_modules/react/dist/react.min.js') // 直接给定取别名的路径
    },
    modules: [path.resolve(__dirname, 'node_modules')], // 安装第三方包是在node_modules目录下,那么在引进第三方包的时候直接到node_module目录下查找
    extensions: ['.js'], // 指定查找文件的类型
    mainFields: ['main']   // 发布到npm上的包会指定入口路径,即main字段的值,即查找文件只在该路径下查找
}

栗子:tree shaking(摇树优化)

概念:1个模块可能有多个方法,只要其中某个方法使用到,则整个文件就会被打包到bundle,而tree shaking只是把用到的方法打包到bundle里面,没用到的方法会在uglify阶段擦除掉

使用:webpack默认支持,在.babelrc设置modules:false即可,注意:mode:production情况下默认开启

要求:必须是ES6语法,cjs方式不支持

无用的css如何删除?

PurifyCSS:遍历代码,识别已经用到的的css class

uncss:HTML需要通过jsdom加载,所有的样式通过PostCSS解析,通过document.querySelector来识别在html文件里面不存在的选择器

在webpack中如何使用PurifyCSS

使用purgecss-webpack-plugin和min-css-extract-plugin配合使用

1)安装插件purgecss-webpack-plugin

npm i purgecss-webpack-plugin -D

2)在项目中把插件引进来

下面写法是单文件入口写法,参考地址:https://www.npmjs.com/package/purgecss-webpack-plugin

const PurgeCSSPlugin = require('purgecss-webpack-plugin')

const PATHS = {
  src: path.join(__dirname, 'src')
}




 plugins: [
    new PurgeCSSPlugin({
      paths: glob.sync(`${PATHS.src}/**/*`,  { nodir: true }),
    })
 ]

栗子:图片压缩

要求:基于Node库的imagemin或者tinypng API

使用:配置image-webpack-loader

使用参考文档:https://www.npmjs.com/package/image-webpack-loader

1)安装插件

npm install image-webpack-loader -D

2)在配置文件中设置

module.exports.module.rules = [{
                test: /\.(png|jpg|jpeg|gif|svg)$/,
                use: [
                    {
                        loader: 'file-loader',
                        options: {
                            name: 'img_[name][hash:8].[ext]'
                        }
                    },
                    {
                        loader: 'image-webpack-loader',
                        options: {
                          mozjpeg: {
                            progressive: true,
                          },
                          // optipng.enabled: false will disable optipng
                          optipng: {
                            enabled: false,
                          },
                          pngquant: {
                            quality: [0.65, 0.90],
                            speed: 4
                          },
                          gifsicle: {
                            interlaced: false,
                          },
                          // the webp option will enable WEBP
                          webp: {
                            quality: 75
                          }
                        }
                    }
                ]
            }]

栗子:构建体积优化,动态polyfill

使用polyfill-service:只给用户返回需要的polyfill,ua识别,下发不同的polyfill

三、通过源代码,掌握webpack打包原理

栗子:webpack启动过程分析

项目启动的时候发生了什么?

一般启动项目,我们都会砸控制台输入npm run dev等语句,然后项目就启动,或者在控制台输入webpack entry.js bundle.js也能直接运行--------这个过程发生什么???

当执行上面语句的时候,npm会让命令行工具进入node_modules/.bin目录查找是否存在webpack.sh webpack.cmd文件,存在就执行,否则抛错;实际的入口文件路径:node_modules/webpack/bin/webpack.js(这里定义了命令,但是是webpack包还是webpack-cli包那个提供的命令?

全局安装的包,会从userLocal/.bin下查找,但是webpack我们一般是局部安装,即安装到具体项目里面,所以会从项目的根目录下的node_modules/.bin去查找文件

局部安装包的时候,想再.bin目录下有这个命令,就必须在package.json的bin字段进行指定

看下node_modules/.bin/webpack文件里面定义了什么

process.exitCode = 0  // 正常执行返回
const runCommand = (command, args) => {}      // 运行某个命令
const isInstalled = packageName => {}     // 判断某个包是否安装了
const CLIs = [....]  // webpack可以用的cli:webpack-cli    webpack-command
const isntalledClis = CLIs.filter(cli => cli.installed)   // 判断安装了那些cli
if (isntalledClis.length === 0) {// 根据安装数量进行处理
} else if (isntalledClis.length === 1) {
} else {
}

启动后的结果:

webpack最终找到webpack-cli(webpack-command)这个npm包,并且执行cli

栗子:webpack-cli源码阅读

猜你喜欢

转载自blog.csdn.net/tangxiujiang/article/details/111773610