webpack

webpack 的用途

  • 帮我们处理 依赖的文件(依赖的资源)
  • 转换 依赖的模块 (浏览器不支持的模块)
  • 项目优化

先初始化

npm init -y   初始化后会自动创建package.json文件

本地安装webpack

npm install webpack webpack-cli --save-dev

查看webpack 版本

webpack -v

npm 的版本在5.2以上 就可以用 npx

0 配置打包

npx webpack
package.json文件中手动设置 执行的命令
"scripts": {
    // "test": "echo \"Error: no test specified\" && exit 1"
    用下面这些写法 把上面的这一步删除
    "dev": "webpack  --mode development",  // 开发环境
    "build":"webpack  --mode production",  // 生产环境
    "dev:server": "webpack-dev-server"
    自己配置好后 用 npm run dev / build / dev:server 去使用
}

将每次打包后的js要插入到html中,在浏览器端查看(需要下载下面这个插件)然后再webpack.config.js中引入
npm i --save-dev html-webpack-plugin (开发依赖)

配置本机的开发服务(自动帮我们启动一个服务 并且在浏览器中打开) (这个插件是一个命令,需要自己去package.json文件中的 scripts中配置)
这个插件打包的内容是在保存在内存里面的 我们是看不到的
npm install webpack-dev-server --save-dev

加载css需要两个loader
npm install --save-dev css-loader npm install --save-dev style-loader

加载less
npm install --save-dev less less-loader

样式处理工具 可以借助自定义的插件从而重新定义css
加私有前缀的插件 autoprefixer
需要在根目录下创建一个 postcss.config.js文件 在这里面去引入自定义的插件
需要在根目录下再创建一个.browserslistrc文件 里面填写参数 cover 99.5% 可以覆盖99.5%的浏览器 这样不同的浏览器都会加上前缀(不论高版本还是低版本)
npm i -D postcss-loader autoprefixer

分离出来css文件
npm install --save-dev mini-css-extract-plugin

压缩js文件(生产环境) 不加D是生产环境下
npm install terser-webpack-plugin

压缩css文件(生产环境) 不加D是生产环境下
npm install optimize-css-assets-webpack-plugin

清理输出的目录(每一次打包都会清理dist里面的内容)
npm install --save-dev clean-webpack-plugin

file-loader url-loader
file-loader: 加载图片 把图片拷贝到 dist目录下
url-loader: 把图片解析成base64
npm install file-loader url-loader --D ( 给 url-loader的 options下面加一个 esModule: false 必须加 )

专门用来处理html文件中的图片
npm install html-withimg-loader --save
解决办法:esModule: false // 该项默认为true,改为false即可
esModule: true该配置项为图片打包后的默认路径,带default对象,
默认为ture,在配置项里将此项改为false即可去掉多余的defalut
对象,

babel
npm install babel-loader @babel/core @babel/preset-env --D
babel-loader babel和 webpack的桥梁(webpack可以通过babel来编译我们的代码)(匹配 js后缀的文件 解析)
@babel/core babel的核心模块(放了babel所有的核心模块)(在核心模块里设置一些预设 或者插件)
@babel/preset-env 主要是把ES6 转换为 ES5 它是一个插件的集合(预设)

npm install --save core-js@3
类似于 babel/polyfill 可以解析高版本的语法

@babel/plugin-transform-runtime @babel/runtime
第一个插件 调用第二个插件 解决冗余(多余)的代码 把公共的方法提取出来

解决草案的插件

npm install --save-dev @babel/plugin-proposal-class-properties
npm install --save-dev @babel/plugin-proposal-decorators // 解决装饰器
装饰器的插件必须在 类插件的前面 如果装饰器的"legacy": true 那么必须 “loose”: true

npm install jquery -D

暴露全局变量 (暴露第三方库)

1、直接使用cdn的方式
2、providePlugin   "$":"jquery"
3、暴露的方式 expose-loader   (npm install expose-loader -D)

添加eslint.js

1、手动 (去官网 https://eslint.org/demo 里面下载 eslintrc.json 拉过来调用)
npm install eslint eslint-loader -D
2、自动
npx eslint --init (初始化配置文件)

sourceMap(代码排查错误)

  • eval 生成代码 每个模块都被 eval执行,每一个打包后的模块后面都增加了包含 sourceURL
  • source-map 产生map文件
  • inline 不会生成独立的 .map文件,会以dataURL形式插入
  • cheap 忽略打包后的列信息,不使用 loader中的 sourcemap
  • module 没有列信息,使用loader中的 sourcemap(没有列信息)

开发环境推荐: cheap-module-eval-source-map
生产环境推荐: cheap-module-source-map

图片压缩

npm install image-webpack-loader --save-dev

Tree-shaking(生产环境下)(副作用 无作用的代码)

  • sideEffects 唯一一个设置在package.json的配置
    “sideEffects”: [ “**/*.css” ], 生产环境下打包才有用 开发环境下 无效

Scope-Hoisting

webpack4 后不用配,天生自带 减少作用域提升性能

热更新

css 自带热更新效果 我们把css样式抽离后 就无发实现热更新 css热更新是在(style-loader里面去设置控制)

  • hot:true
  • HotModuleReplacementPlugin
  • module.hot.accept

懒加载(动态加载)

  • webpackChunkName(可以设置动态加载出来的文件名) chunkFilename
  • webpackPrefetch
  • webpackPreload
  • @babel/plugin-syntax-dynamic-import
  • @babel/preset-react

打包文件分析工具(生成环境下使用)

默认就会展现当前应用的分析图表
安装webpack-bundle-analyzer插件
npm install --save-dev webpack-bundle-analyzer
const {BundleAnalyzerPlugin} = require(‘webpack-bundle-analyzer’);

DllPlugin & DlLReferencePlugin (一般用在开发环境下)

把第三方库打包成动态链接库,以后构建时只需要查找构建好的库就好了,这样可以大大节约构建时间
-add-asset-html-webpack-plugin

多入口多出口

SplitChunks

编译时抽离第三方模块、公共模块

happypack

多线程打包,可以讲不同的逻辑交给不同的线程来处理

根据Mode分离配置环境

// 遵循 commonjs 规范

const path = require('path')

// 引入插件
const HtmlWebpackPlugin = require('html-webpack-plugin')

// 引入分离css的插件
const MiniExtractPlugin = require("mini-css-extract-plugin")

const TerserJSPlugin = require('terser-webpack-plugin'); // 压缩js
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin'); // 压缩css

const { CleanWebpackPlugin } = require('clean-webpack-plugin');

const webpack = require("webpack")

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

let htmlPlugins = ["index", "other"].map(chunkName => {
    return new HtmlWebpackPlugin({
        // 把打包后的js自动的引用到新生成的html文件中
        template: path.resolve(__dirname, `./${chunkName}.html`),
        filename: `${chunkName}.html`,
        minify: false,
        chunks: [`${chunkName}`]
    })
})

module.exports = {
    devtool: "cheap-module-eval-source-map",   // 代码报错后 【准确】显示出来哪一行 为何报错
    // externals: {
    //     "jquery": "$"   // 如果是第三方库jQuery就需要打包
    // },

    // 抽离公共的库 第三方模块
    optimization: {
        splitChunks: {
            chunks: 'all',   // async 异步代码   all 所有
            minSize: 30000,   // 最少30kb采取抽离
            minRemainingSize: 0,
            maxSize: 0,
            minChunks: 1,   //最少引用模块一次
            maxAsyncRequests: 6,   // 异步模块请求最多不超过6次
            maxInitialRequests: 4,   // 首屏请求次数不超过3次
            automaticNameDelimiter: '~',   // 抽离模块名称的连接符
            name: true,   // 可以更改模块名
            cacheGroups: {   // 自己设定一些规则
                // defaultVendors: {
                //     test: /[\\/]node_modules[\\/]/,
                //     priority: -10   // 优先级
                // },
                default: {   // 抽离的模块名 名字默认是 default开头
                    minChunks: 2,
                    priority: -20,
                    reuseExistingChunk: true
                }
            }
        }
    },

    /*
        entry: 入口文件 
        output: 出口文件
        filename: 用于设置打包的 js文件名字
        path: 打包后的路径
        __dirname: commonjs 规范里面提供的 API 主要目的 定位所在文件的项目根目录
    */
    entry: {   // 配置多入口多出口
        index: "./src/index.js",
        // other: "./src/other.js"
    },
    output: {
        filename: "[name].js",   // chunkhash 是以入口文件为基准的hash值   content 是以文件为基准的hash值
        path: path.resolve(__dirname, "dist"), // 这一步返回一个绝对的路径
        chunkFilename: "[name].min.js"   // 设置异步请求的文件名
    },
    // webpack4 提供的压缩选项
    optimization: {
        minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],
    },
    devServer: {
        port: 7878, // 端口号
        // open: true, // 打包后 自动打开
        compress: true, // 启动gzip压缩
        contentBase: "aa", // aa目录下的静态资源文件也可以直接访问
        // 若是要访问 aa静态资源里面的内容 直接在自动打开的浏览器窗口地址中输入你想要打开的静态资源 是帮我们配置好的
        //比如 这个是自动打开的地址 http://localhost:9999 想要打开静态资源直接在后面输入即可   http://localhost:9999/a.html

        // 模拟数据(后端数据没写好之前)
        before(app) {   // after 以9999端口号创建一个服务,这样没有跨域问题
            app.get("/api/user", function (req, res) {
                console.log(res.json({ name: "xw" }));
            })
        },
        hot: true

        // proxy: {
        //     // 配置跨域请求
        //     "/api": {
        //         target: "http://localhost:6000",   // 设置请求的服务器地址
        //         pathRewrite: { "/api": "" },   // 重写路径
        //         changeOrigin: true   // 把请求头里面 host的地址改成服务器地址(为true表示是6000当前服务器的地址,为false表示服务器端的接口地址)
        //         // secure: false   // 代理的服务器是 https
        //     }
        // }
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin(),
        new CleanWebpackPlugin(),
        // new MiniExtractPlugin({
        //     filename: "css/main.css"
        // }),

        new HtmlWebpackPlugin({
            // 把打包后的js自动的引用到新生成的html文件中
            template: path.resolve(__dirname, "./index.html"),
            filename: "index.html",
            minify: false,
            // chunks: ["index"]
        }),
        // new HtmlWebpackPlugin({
        //     // 把打包后的js自动的引用到新生成的html文件中
        //     template: path.resolve(__dirname, "./other.html"),
        //     filename: "other.html",
        //     minify: false,
        //     chunks: ["other"]
        // }),
        // ...htmlPlugins,

        // new webpack.ProvidePlugin({   // 可以把变量变成每个模块都能使用的,但是并不是window上的 这个插件需要配合cdn一起使用
        //     "$": "jquery"   // $ 变量 是jQuery中的
        // })

        // 分析图表
        // new BundleAnalyzerPlugin()
    ],
    module: {   // 确定下对什么文件进行转换,怎么转换,需要哪些loader
        rules: [   // rules 是从下往上进行解析的,从右往左,确定好规则
            // {
            //     test: /\.css$/,   // 匹配文件
            //     use: "style-loader"  // use 后面的值可以是   空对象("")   数组([])   对象({})
            // },
            // {
            //     test: /\.css$/,
            //     use: "css-loader"
            // }
            {
                // eslint 要在所有规则之前配置
                test: /\.js$/,
                use: "eslint-loader",
                exclude: /node_modules/,   // 排除哪些文件
                // include: path.resolve(__dirname, "src/**/*"),   // 校验包含哪些文件
                enforce: "pre"   // 在所有规则之前先校验代码
            },
            {
                test: require.resolve("jquery"),
                use: {
                    loader: "expose-loader",
                    options: "$"
                }
            },
            {
                test: /\.css$/,
                use: [//"style-loader",   // 把css分离出来不用 "style-loader" 用 "link" 因为js是单线程 所以要用link 可以提高css加载速率
                    // {
                    //     loader: MiniExtractPlugin.loader
                    // },
                    {
                        loader: "style-loader"
                    },
                    {
                        loader: "css-loader",
                        options: {
                            importLoaders: 2   // 用后面几个加载器解析 写几个就用几个
                        }
                    }, "postcss-loader", "less-loader"
                ]
            },
            {
                // 配置less
                test: /\.less$/,
                use: ["style-loader", "css-loader", "less-loader"]
            },
            // {
            //     test: /\.(png|jpe?g|gif)/,
            //     use: "file-loader"
            // }
            {
                // 把图片转换为base64
                test: /\.(png|jpe?g|gif)$/,
                // 10kb 以内的通过url-loader转换成 base64,大于 10kb的通过file-loader拷贝一份放在dist目录下
                use: [
                    // loader: "url-loader",
                    // options: {
                    //     limit: 10 * 1024,   // 110kb
                    //     outputPath: 'img',  // 设置图片的存放路径
                    //     // publicPath: "xiaoyu/img"   // 把图片放到别的服务器中 并设置绝对路径前缀
                    //     esModule: false // 该项默认为true,改为false即可
                    // }

                    // 下面是配置压缩图片
                    { loader: "file-loader" },
                    {
                        loader: 'image-webpack-loader',
                        options: {
                            mozjpeg: {
                                progressive: true,
                                quality: 65
                            },
                            // 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
                            }
                        }
                    }
                ]
            },
            {
                // 配置 iconfont 字体图标
                test: /\.(eot|svg|ttf|woff|woff2)$/,
                use: "file-loader"
            },
            {
                test: /\.html$/,
                use: "html-withimg-loader"
            },
            {
                // 配置babel (可以专门创建一个文件.babelrc 用来存储预设或者插件 因为后期要配多个)
                test: /\.js$/,
                use: {
                    loader: "babel-loader",
                    // options: {   把options里面的配置放到 .babelrc文件中
                    //     presets: ["@babel/preset-env"], // 预设 也就是插件的集合
                    //     plugins: []  // 放置一个个的插件
                    // }
                }
            }
        ]
    }
}
.browserslistrc 文件中的代码如下

cover 99.5%
//适配 99.5% 的浏览器
postcss.config.js 文件中的代码如下

module.exports = {
    plugins: [
        require("autoprefixer")
    ]
}
// (加前缀 不论高低版本)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值