玩转webpack(02):webpack基础使用

一、核心概念——entry

Entry用于指定webpack打包的入口

 1、单入口(entry是一个字符串)

module.exports = {
    entry: './src/index.js'
}

2、多入口(entry是一个对象)

module.exports = {
    entry:{
        app: './app.js',
        adminApp: './src/adminApp.js'
    }
}

二、核心概念——output

output用来告诉webpack如何将编译后的文件输出到磁盘

1、单入口

module.exports = {
    entry: './src/index.js',
    output: {
        filename: 'bundle.js',
        path: __dirname + '/dist'
    }
}

2、多入口

module.exports = {
    entry:{
        app: './app.js',
        adminApp: './src/adminApp.js'
    },
    output: {
        filename: '[name].js', // 通过占位符确保文件名的唯一
        path: __dirname + '/dist'
    }
}

三、核心概念——loaders

webpack默认只支持js和json两种文件类型,通过loaders去支持其他文件类型并且把他们转化成有效的模块,并且可以添加到依赖图中。


本身是一个函数,接受源文件作为参数,返回转换的结果。

1、常见的loader

名称描述
babel-loader转换ES6、ES7等JS新特性语法
css-loader支持.css文件的加载和解析
less-loader将less转换为css
ts-loader将TS转换成JS
file-loader进行图片、字体的打包
raw-loader将文件以字符串的形式导入
thread-loader多进程打包JS和CSS

2、loader的用法

module:{
    rules: [
        {
            test: /\.txt$/,    // test:指定匹配规则
            use: 'raw-loader'    // use:指定使用的loader名称
        }
    ]
}

四、核心概念——plugins

插件用于bundle文件的优化,资源管理和环境变量注入

作用于整个构建过程

1、常见的plugins

名称描述
CommonsChunkPlugin将chunks相同的模块代码提取成公共js
CleanWebpackPlugin清理构建目录
ExtractTextWebpackPlugin将css从bundle文件里提取成一个独立的css文件
CopyWebpackPlugin将文件或者文件夹拷贝到构建的输出目录
HtmlWebpackPlugin创建html文件去承载输出的bundle
UglifyjsWebpackPlugin压缩JS
ZipWebpackPlugin将打包的资源输出生成一个zip包

2、plugins用法

plugins:[
    new HtmlWebpackPlugin({    // 放到plugins数组里
        template: './src/index.html'
    })
]

五、核心概念——mode

mode用来指定当前的构建环境是:production、develoment还是node

设置mode可以使用webpack内置的函数,默认值为production

1、mode的内置函数功能

选项描述
development设置 process.env.NODE_ENV 的值为 development.开启 NamedChunksPlugin 和 NamedModulesPlugin .
production设置 process.env.NODE_ENV 的值为 production.开启
FlagDependencyUsagePlugin , FlagInclu dedChunksPlugin ModuleConcatenationPlugin , NoEmitOnE rrorsPlugin , Occurrence0rderPlugin ,SideEffectsFl agPlugin 和 TerserPlugin .
none不开启任何优化选项

六、使用

1、使用babel-loader解析ES6和React JSX

babel的配置文件是:.babelrc

(1)安装

npm install -D babel-loader @babel/core @babel/preset-env @babel/preset-react
npm i react react-dom

(2)增加ES6的babel preset配置 (.babelrc)

{
    "presets": [
        "@babel/preset-env",
        "@babel/preset-react"
    ]
}

(3)新增文件reactTest.js

'use strict';
import React from "react";
import ReactDOM from "react-dom";

class ReactComponents extends React.Component {
    render() {
        return <div>Hello React</div>;
    }
}

ReactDOM.render(
    <ReactComponents />,
    document.getElementById('root')
)

(4) 修改webpack.config.js

 'use strict'

 const path = require('path');
 module.exports = {
    entry: {
        main: './src/index.js',
        reactTest: './src/reactTest.js'
    },
    output: {
        path: path.join(__dirname, 'dist'),
        filename: '[name].js'
    },
    mode: 'production',
    module: {
        rules: [
            {
                test: /\.js$/,
                use: 'babel-loader'
            }
        ]
    }
 }

2、css、less、sass解析

css-loader用于加载.css文件,并且转换成commonjs对象

style-loader将样式通过<style>标签插入head中

(1)安装依赖

npm i css-loader style-loader -D

(2)修改webpack.config.js

 'use strict'

 const path = require('path');
 module.exports = {
    entry: {
        main: './src/index.js',
        reactTest: './src/reactTest.js'
    },
    output: {
        path: path.join(__dirname, 'dist'),
        filename: '[name].js'
    },
    mode: 'production',
    module: {
        rules: [
            {
                test: /\.js$/,
                use: 'babel-loader'
            },
            {
                test: /\.css$/,
                // use数组中是从后往前调用的
                use: [
                    'style-loader',
                    'css-loader',
                ]
            }
        ]
    }
 }

 (3)新增文件reactTest.css

.react-test{
    font-size: 20px;
    color: red;
}

(4)修改reactTest.js

'use strict';
import React from "react";
import ReactDOM from "react-dom";
import './reactTest.css';

class ReactComponents extends React.Component {
    render() {
        return <div className="react-test">Hello React</div>;
    }
}

ReactDOM.render(
    <ReactComponents />,
    document.getElementById('root')
)

 (5)解析less和sass

less-loader用于将less转换成css

npm i less less-loader -D
 'use strict'

 const path = require('path');
 module.exports = {
    entry: {
        main: './src/index.js',
        reactTest: './src/reactTest.js'
    },
    output: {
        path: path.join(__dirname, 'dist'),
        filename: '[name].js'
    },
    mode: 'production',
    module: {
        rules: [
            {
                test: /\.js$/,
                use: 'babel-loader'
            },
            {
                test: /\.css$/,
                // use数组中是从后往前调用的
                use: [
                    'style-loader',
                    'css-loader',
                    'less-loader'
                ]
            },
            {
                test: /\.less$/,
                use: [
                    'style-loader',
                    'css-loader',
                    'less-loader'
                ]
            }
        ]
    }
 }

3、解析图片和字体——file-loader

file-loader用于处理文件,也可以用来解析字体

(1)安装依赖 

npm i file-loader -D

(2)修改webpack.config.js

module: {
    rules: [
        {
            test: /\.js$/,
            use: 'babel-loader'
        },
        {
            test: /\.css$/,
            // use数组中是从后往前调用的
            use: [
                'style-loader',
                'css-loader',
                'less-loader'
            ]
        },
        {
            test: /\.less$/,
            use: [
                'style-loader',
                'css-loader',
                'less-loader'
            ]
        },
        {
            test: /\.(png|jpg|gif|jpeg)$/,
            use: 'file-loader'
        },
        {
            test: /\.(woff|woff2|eot|ttf|otf)/,
            use: 'file-loader'
        }
    ]
}

4、解析图片和字体——url-loader

url-loader也可以处理图片和字体

可以设置较小资源自动base64

(1)安装依赖

npm i url-loader -D

(2)修改webpack.config.js

'use strict'

const path = require('path');
module.exports = {
    entry: {
        main: './src/index.js',
        reactTest: './src/reactTest.js'
    },
    output: {
        path: path.join(__dirname, 'dist'),
        filename: '[name].js'
    },
    mode: 'production',
    module: {
        rules: [
            {
                test: /\.js$/,
                use: 'babel-loader'
            },
            {
                test: /\.css$/,
                // use数组中是从后往前调用的
                use: [
                    'style-loader',
                    'css-loader',
                    'less-loader'
                ]
            },
            {
                test: /\.less$/,
                use: [
                    'style-loader',
                    'css-loader',
                    'less-loader'
                ]
            },
            {
                test: /\.(png|jpg|gif|jpeg)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 10240
                        }
                    }
                ]
            },
            {
                test: /\.(woff|woff2|eot|ttf|otf)/,
                use: 'file-loader'
            },
        ]
    }
}

5、webpack中的文件监听

文件监听是在发现源码发生变化时,自动重新构建出新的输出文件

webpack开启监听模式,有两种方式:

  • 启动webpack命令时,带上 --watch参数
  • 在配置webpack.config.js中设置watch:true

唯一缺陷:每次需要手动刷新浏览器

(1)修改package.json 后运行 npm run watch

{
  "name": "webpackExercise",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack",
    "watch": "webpack --watch"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.20.2",
    "@babel/preset-env": "^7.20.2",
    "@babel/preset-react": "^7.18.6",
    "babel-loader": "^9.1.0",
    "css-loader": "^6.7.2",
    "file-loader": "^6.2.0",
    "less": "^4.1.3",
    "less-loader": "^11.1.0",
    "style-loader": "^3.3.1",
    "url-loader": "^4.1.1",
    "webpack": "^5.75.0",
    "webpack-cli": "^5.0.0"
  },
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  }
}

 (2)原理

轮询判断文件的最后编辑时间是否变化

某个文件发生了变化,并不会立刻告诉监听者,而是先缓存起来,等aggregateTimeout

'use strict'

const path = require('path');
module.exports = {
    // 默认false,不开启
    watch: true,
    watchOptions: {
        // 忽略监听的文件
        ignored: /node_modules/,
        // 监听到变化后会等300毫秒再去执行,默认300毫秒
        aggregateTimeout: 300,
        // 判读文件是否发生变化是通过轮询指定文件,默认每秒轮询1000次
        poll: 1000
    },
    entry: {
        main: './src/index.js',
        reactTest: './src/reactTest.js'
    },
    output: {
        path: path.join(__dirname, 'dist'),
        filename: '[name].js'
    },
    mode: 'production',
    module: {
        rules: [
            {
                test: /\.js$/,
                use: 'babel-loader'
            },
            {
                test: /\.css$/,
                // use数组中是从后往前调用的
                use: [
                    'style-loader',
                    'css-loader',
                    'less-loader'
                ]
            },
            {
                test: /\.less$/,
                use: [
                    'style-loader',
                    'css-loader',
                    'less-loader'
                ]
            },
            {
                test: /\.(png|jpg|gif|jpeg)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 10240
                        }
                    }
                ]
            },
            {
                test: /\.(woff|woff2|eot|ttf|otf)/,
                use: 'file-loader'
            },
        ]
    }
}

6、热更新:webpack-dev-server(HotModuleReplacementPlugin)

(1)安装依赖 

npm i webpack-dev-server -D

webpack-dev-server不刷新浏览器

webpack-dev-server不输出文件,而是放在内存中

使用HotModuleReplacementPlugin插件

(2)修改package.json 

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack",
    "watch": "webpack --watch",
    "dev": "webpack-dev-server --open"
  },

(3)修改webpack.config.js 

'use strict'

const path = require('path');
const webpack = require('webpack');
module.exports = {
    // // 默认false,不开启
    // watch: true,
    // watchOptions: {
    //     // 忽略监听的文件
    //     ignored: /node_modules/,
    //     // 监听到变化后会等300毫秒再去执行,默认300毫秒
    //     aggregateTimeout: 300,
    //     // 判读文件是否发生变化是通过轮询指定文件,默认每秒轮询1000次
    //     poll: 1000
    // },
    entry: {
        main: './src/index.js',
        reactTest: './src/reactTest.js'
    },
    output: {
        path: path.join(__dirname, 'dist'),
        filename: '[name].js'
    },
    mode: 'development',
    module: {
        rules: [
            {
                test: /\.js$/,
                use: 'babel-loader'
            },
            {
                test: /\.css$/,
                // use数组中是从后往前调用的
                use: [
                    'style-loader',
                    'css-loader',
                    'less-loader'
                ]
            },
            {
                test: /\.less$/,
                use: [
                    'style-loader',
                    'css-loader',
                    'less-loader'
                ]
            },
            {
                test: /\.(png|jpg|gif|jpeg)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 10240
                        }
                    }
                ]
            },
            {
                test: /\.(woff|woff2|eot|ttf|otf)/,
                use: 'file-loader'
            },
        ]
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin()
    ],
    devServer: {
        static: './dist',
        hot: true
    }
}

 注:在新版的webpack-dev-server中,contentBase已经被移除了,用static替代。

7、热更新:webpack-dev-middleware

webpack-dev-middleware将webpack输出的文件传输给服务器

适用于灵活的定制场景


webpack compile:将js编译成bundle

HMR server:将热更新的文件输出给HMR Runtime

bundle server:提供文件在浏览器的访问

HMR runtime:会被注入到浏览器,更新文件的变化

bundle.js:构建输出的文件 

8、文件指纹策略 

打包后输出的文件名的后缀,通常做的是文件发布的版本管理

(1)文件指纹如何生成

  • Hash:和整个项目的构建相关,只要项目文件有修改,整个项目构建的hash值就会更改
  • Chunkhash:和webpack打包的chunk有关,不同的enty会生成不同的chunkhash值
  • Contenthash:根据文件内容来定义hash,文件内容不变,则contenthash不变

(2)js的文件指纹设置

设置output的filename,使用 [chunkhash]

(3)css的文件指纹设置

// 提取css文件
npm i mini-css-extract-plugin -D

设置MiniCssExtractPlugin的filename,使用 [contenthash]

(4)图片或字体的文件指纹设置

设置file-loader的name,使用 [hash] 

占位符名称含义
[ext]资源后缀名
[name]文件名称
[path]文件的相对路径
[folder]文件所在的文件夹
[contnthash]文件内容的hash,默认md5生成
[hash]文件内容的hash,默认md5生成
[emoji]一个随机的指代文件内容的enoj

(5)修改package.json

"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack --config webpack.prod.js",
    "watch": "webpack --watch",
    "dev": "webpack-dev-server --config webpack.dev.js --open"
  },

 (6)新建文件webpack.prod.js,并将原有的webpack.config.js改为webpack.dev.js

'use strict'

const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
    entry: {
        main: './src/index.js',
        reactTest: './src/reactTest.js'
    },
    output: {
        path: path.join(__dirname, 'dist'),
        filename: '[name]_[chunkhash:8].js'
    },
    mode: 'production',
    module: {
        rules: [
            {
                test: /\.js$/,
                use: 'babel-loader'
            },
            {
                test: /\.css$/,
                // use数组中是从后往前调用的
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader'
                ]
            },
            {
                test: /\.less$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'less-loader'
                ]
            },
            {
                test: /\.(png|jpg|gif|jpeg)$/,
                use: [
                    {
                        loader: 'file-loader',
                        options: {
                            name: '[name]_[hash:8].[ext]'
                        }
                    }
                ]
            },
            {
                test: /\.(woff|woff2|eot|ttf|otf)/,
                use: [
                    {
                        loader: 'file-loader',
                        options: {
                            name: '[name]_[hash:8].[ext]'
                        }
                    }
                ]
            },
        ]
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: '[name]_[contenthash:8].css'
        })
    ]
}

9、HTML、CSS、JS压缩 

(1)JS压缩

webpack5内置了terser-webpack-plugin,如果需要额外配置需要安装terser-webpack-plugin并进行一系列调整

(2)CSS文件的压缩 

webpack5中可使用css-minimizer-webpack-plugin

npm install css-minimizer-webpack-plugin --save-dev
// webpack.prod.js
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

// ...
    plugins: [
        new MiniCssExtractPlugin({
            filename: '[name]_[contenthash:8].css',
        })
    ],
    optimization: {
        minimizer: [
            new CssMinimizerPlugin(),
        ],
    },

 (3)HTML压缩

npm install --save-dev html-webpack-plugin
const HtmlWebpackPlugin = require('html-webpack-plugin');

    plugins: [
        new MiniCssExtractPlugin({
            filename: '[name]_[contenthash:8].css',
        }),
        new HtmlWebpackPlugin({
            template: path.join(__dirname, 'src/index.html'),
            filename: 'index.html',
            chunks: ['index'],
            inject: true,
            minify: {
                html5: true,
                collapseWhitespace: true,
                preserveLineBreaks: false,
                minifyCSS: true,
                minifyJS: true,
                removeComments: false
            }
        }),
    ],

10、一份prod配置

'use strict'

const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    entry: {
        index: './src/index.js',
        reactTest: './src/reactTest.js'
    },
    output: {
        path: path.join(__dirname, 'dist'),
        filename: '[name]_[chunkhash:8].js'
    },
    mode: 'production',
    module: {
        rules: [
            {
                test: /\.js$/,
                use: 'babel-loader'
            },
            {
                test: /\.css$/,
                // use数组中是从后往前调用的
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader'
                ]
            },
            {
                test: /\.less$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'less-loader'
                ]
            },
            {
                test: /\.(png|jpg|gif|jpeg)$/,
                use: [
                    {
                        loader: 'file-loader',
                        options: {
                            name: '[name]_[hash:8].[ext]'
                        }
                    }
                ]
            },
            {
                test: /\.(woff|woff2|eot|ttf|otf)/,
                use: [
                    {
                        loader: 'file-loader',
                        options: {
                            name: '[name]_[hash:8].[ext]'
                        }
                    }
                ]
            },
        ]
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: '[name]_[contenthash:8].css',
        }),
        new HtmlWebpackPlugin({
            template: path.join(__dirname, 'src/reactTest.html'),
            filename: 'reactTest.html',
            chunks: ['reactTest'],
            inject: true,
            minify: {
                html5: true,
                collapseWhitespace: true,
                preserveLineBreaks: false,
                minifyCSS: true,
                minifyJS: true,
                removeComments: false
            }
        }),
        new HtmlWebpackPlugin({
            template: path.join(__dirname, 'src/index.html'),
            filename: 'index.html',
            chunks: ['index'],
            inject: true,
            minify: {
                html5: true,
                collapseWhitespace: true,
                preserveLineBreaks: false,
                minifyCSS: true,
                minifyJS: true,
                removeComments: false
            }
        }),
    ],
    optimization: {
        minimize: true,
        minimizer: [
            new CssMinimizerPlugin(),
        ],
    },
}

11、一份dev配置

'use strict'

const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
    // // 默认false,不开启
    // watch: true,
    // watchOptions: {
    //     // 忽略监听的文件
    //     ignored: /node_modules/,
    //     // 监听到变化后会等300毫秒再去执行,默认300毫秒
    //     aggregateTimeout: 300,
    //     // 判读文件是否发生变化是通过轮询指定文件,默认每秒轮询1000次
    //     poll: 1000
    // },
    entry: {
        index: './src/index.js',
        reactTest: './src/reactTest.js'
    },
    output: {
        path: path.join(__dirname, 'dist'),
        filename: '[name][chunkhash].js'
    },
    mode: 'development',
    module: {
        rules: [
            {
                test: /\.js$/,
                use: 'babel-loader'
            },
            {
                test: /\.css$/,
                // use数组中是从后往前调用的
                use: [
                    'style-loader',
                    'css-loader',
                ]
            },
            {
                test: /\.less$/,
                use: [
                    'style-loader',
                    'css-loader',
                    'less-loader'
                ]
            },
            {
                test: /\.(png|jpg|gif|jpeg)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 10240
                        }
                    }
                ]
            },
            {
                test: /\.(woff|woff2|eot|ttf|otf)/,
                use: 'file-loader'
            },
        ]
    },
    plugins: [
        new webpack.HotModuleReplacementPlugin(),
        new HtmlWebpackPlugin({
            template: path.join(__dirname, 'src/reactTest.html'),
            filename: 'reactTest.html',
            chunks: ['reactTest'],
            inject: true,
            minify: {
                html5: true,
                collapseWhitespace: true,
                preserveLineBreaks: false,
                minifyCSS: true,
                minifyJS: true,
                removeComments: false
            }
        }),
        new HtmlWebpackPlugin({
            template: path.join(__dirname, 'src/index.html'),
            filename: 'index.html',
            chunks: ['index'],
            inject: true,
            minify: {
                html5: true,
                collapseWhitespace: true,
                preserveLineBreaks: false,
                minifyCSS: true,
                minifyJS: true,
                removeComments: false
            }
        }),
    ],
    devServer: {
        static: './dist',
        hot: true
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值