【webpack4系列】webpack基础用法(二)

news2024/9/22 5:38:06

文章目录

    • entry
    • output
    • loader
    • plugin
    • mode
    • 前端构建基础配置
      • 关联HTML插件html-webpack-plugin
      • 构建 CSS
    • 解析 ES6和React JSX
      • 解析 ES6
      • 解析 React JSX
    • 解析CSS、Less和Sass
      • 解析CSS
      • 解析Less
      • 解析sass
    • 解析图片和字体
      • 资源解析:解析图片
      • 资源解析:解析字体
      • 资源解析:使用url-loader
    • webpack中的文件监听
    • webpack中的热更新及原理分析
      • 热更新:webpack-dev-server
      • 热更新:使⽤ webpack-dev-middleware
    • 文件指纹策略:chunkhash、contenthash和hash
      • 文件指纹如何生成
      • 文件指纹设置
    • HTML 、CSS和JavaScript代码压缩
      • JS压缩
      • CSS压缩
      • HTML压缩

webpack 本质上是一个打包工具,它会根据代码的内容解析模块依赖,帮助我们把多个模块的代码打包。

在这里插入图片描述

一切文件:JavaScript、CSS、SCSS、图片、模板,在 Webpack 眼中都是一个个模块,这样的好处是能清晰的描述出各个模块之间的依赖关系,以方便 Webpack 对模块进行组合和打包。 经过 Webpack 的处理,最终会输出浏览器能使用的静态资源。

entry

webpack 构建的入口entry,webpack 会读取这个文件,并从它开始解析依赖,在内部构件一个依赖图,这个依赖图会引用项目中使用到的各个模块,然后进行打包,生成一个或者多个 bundle 文件。

我们常见的项目中,如果是单页面应用,那么入口只有一个;如果是多个页面的项目,那么通常是一个页面会对应一个构建入口。

单⼊⼝:entry 是⼀个字符串,如下代码:

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

上述代码等价于:

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

多⼊口:entry 是⼀个对象,如下代码:

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

还有一种场景比较少用到,即是多个文件作为一个入口来配置,webpack 会解析多个文件的依赖然后打包到一起:

// 使用数组来对多个文件进行打包
module.exports = {
  entry: {
    main: [
      './src/foo.js',
      './src/bar.js'
    ]
  }
}

动态 entry

const path = require('path');
const fs = require('fs');

// src/pages 目录为页面入口的根目录
const pagesRoot = path.resolve(__dirname, './src/pages');
// fs 读取 pages 下的所有文件夹来作为入口,使用 entries 对象记录下来
const entries = fs.readdirSync(pagesRoot).reduce((entries, page) => {
  // 文件夹名称作为入口名称,值为对应的路径,可以省略 `index.js`,webpack 默认会寻找目录下的 index.js 文件
  entries[page] = path.resolve(pagesRoot, page);
  return entries;
}, {});

module.exports = {
  // 将 entries 对象作为入口配置
  entry: entries,

  // ...
};

output

output用来告诉 webpack 如何将编译后的文件输出到磁盘。webpack 构建生成的文件名、路径等都是可以配置的,在配置文件中使用 output 字段来进行设置:

module.exports = {
  // ...
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
  },
}

// 或者使用 entry 的名称
module.exports = {
  entry: {
    main: './src/index.js' // main 为 entry 的名称
  },
  output: {
    filename: '[name].js', // 使用 [name] 来引用 entry 名称,在这里即为 main
    path: path.join(__dirname, '/dist/[hash]'),
    // 路径中使用 hash,每次构建时会有一个不同 hash 值,可以用于避免发布新版本时浏览器缓存导致代码没有更新
    // 文件名中也可以使用 hash
  },
}

loader

我们在前端构建中会遇见需要使用各式各样的文件,例如 css 代码,图片,模板代码等。webpack 中提供一种处理多种文件格式的机制,便是使用 loader。我们可以把 loader 理解为是一个转换器,负责把某种文件格式的内容转换成 webpack 可以支持打包的模块。例如我们需要 css-loader 来处理 .css 文件(这里其实还需要 style-loader),最终把不同格式的文件都解析成 js 代码,以便打包后在浏览器中运行。

webpack 开箱即用只支持 JS 和 JSON 两种文件类型,通过 Loaders 去支持其它文件类型并且把它们转化成有效的模块,并且可以添加到依赖图中。
本身是一个函数,接受源文件作为参数,返回转换的结果。

常见的 Loaders 有哪些?

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

示例,处理CSS,一般要安装style-loader、css-loader:

其中webpack4.x安装style-loader2.x、css-loader3.x:

npm i css-loader@3 style-loader@2 -D

如果要使用babel-loader,使用webpack4.x,要安装npm install babel-loader@8 @babel/core @babel/preset-env

babel的一系列工具链说明:

  • @babel/core:babel核心包,babel-loader的核心依赖。
  • @babel/preset-env:ES语法分析包。

注:es6到es5的语法转换是以插件的形式实现的,可以是自己的插件也可以是官方提供的插件如箭头函数转换插件@babel/plugin-transform-arrow-functions。

由此我们可以看出,我们需要转换哪些新的语法,都可以将相关的插件一一列出,但是这其实非常复杂,因为我们往往需要根据兼容的浏览器的不同版本来确定需要引入哪些插件,为了解决这个问题,babel给我们提供了一个预设插件组,即@babel/preset-env,可以根据选项参数来灵活地决定提供哪些插件。

  • @babel/polyfill:@babel/preset-env只是提供了语法转换的规则,但是它并不能弥补浏览器缺失的一些新的功能,如一些内置的方法和对象,如Promise,Array.from等,此时就需要polyfill来做js得垫片,弥补低版本浏览器缺失的这些新功能。

我们需要注意的是,polyfill的体积是很大的,如果我们不做特殊说明,它会把你目标浏览器中缺失的所有的es6的新的功能都做垫片处理。但是我们没有用到的那部分功能的转换其实是无意义的,造成打包后的体积无谓的增大,所以通常,我们会在presets的选项里,配置"useBuiltIns": “usage”,这样一方面只对使用的新功能做垫片,另一方面,也不需要我们单独引入import '@babel/polyfill’了,它会在使用的地方自动注入。

  • babel-loader:理解成一个加载器,webpack通过babel-loader这个中间桥梁告诉webpack怎样去调用@babel/core、@babel/preset-env 、@babel/polyfill这些规则(语法转换和弥补缺失)去编译js。
  • @babel/plugin-transform-runtime:polyfill的垫片是在全局变量上挂载目标浏览器缺失的功能,因此在开发类库,第三方模块或者组件库时,就不能再使用babel-polyfill了,否则可能会造成全局污染,此时应该使用transform-runtime。transform-runtime的转换是非侵入性的,也就是它不会污染你的原有的方法。遇到需要转换的方法它会另起一个名字,否则会直接影响使用库的业务代码。

故开发类库,第三方模块或者组件库时使用transform-runtime,平常的项目使用babel-polyfill即可.

rules的配置如下:

module: {
    rules:[
        {
            test: /\.css$/,
            use: ['style-loader','css-loader']
        },
        {
            test: /\.jsx?$/,  // 匹配文件路径的正则表达式,通常我们都是匹配文件类型后缀
            exclude: /node_modules/, // 排除掉node_modules这个文件夹的js文件
            include: [
                path.resolve(__dirname,'src') // 指定哪些路径下的文件需要经过 loader 处理
            ],
            use: { // 指定使用的 loader
                loader: 'babel-loader', // babel-loader 可以使用 babel 来将 ES6 代码转译为浏览器可以执行的的 ES5 代码
                options: {
                    presets: ['@babel/preset-env']
                }
            }
        }
    ]
}

plugin

插件⽤于 bundle ⽂件的优化,资源管理和环境变量注⼊,作⽤于整个构建过程。

常用的plugin:

  • CommonsChunkPlugin:将chunks相同的模块代码提取成公共js,webpack4.x版本使用optimization.SplitChunks
  • cleanWebpackPlugin:清理构建目录
  • ExtractTextWebpackPlugin:将CSS从bundle文件里提取成一个独立的CSS文件(webpack3.x版本),webpack4.x版本使用mini-css-extract-plugin
  • CopyWebpackPlugin:将文件或者文件夹拷贝到构建的输出目录
  • HtmlWebpackPlugin:创建html文件去承载输出的bundle(webpack4.x使用4.x版本HtmlWebpackPlugin)
  • UglifyjsWebpackPlugin:压缩JS
  • ZipWebpackPlugin:将打包出的资源生成一个zip包
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
  ]
}

在 webpack 的构建流程中,plugin 用于处理更多其他的一些构建任务。可以这么理解,模块代码转换的工作由 loader 来处理,除此之外的其他任何工作都可以交由 plugin 来完成。

例如,使用 copy-webpack-plugin 来复制其他不需要 loader 处理的文件,只需在配置中通过 plugins 字段添加新的 plugin 即可:

webpack4.x安装copy-webpack-plugin@6 版本

 new CopyWebpackPlugin({
  patterns: [
    {
      from: path.resolve(__dirname, "../static"),
      to: 'static',
      globOptions: {
        ignore: [".*"]
      }
    }
  ]
})

mode

mode,构建模式是 webpack4引入的新概念,用于方便快捷地指定一些常用的默认优化配置。

mode取值:

  • development:开发环境
  • production:生产环境
  • none :不需要任何默认优化配置

示例:

module.exports = {
  mode: 'development', // 指定构建模式为 development
  // ...
}

development 和 production 模式的区别:

  • 这两个模式会使用 DefinePlugin 来将 process.env.NODE_ENV 的值分别设置为 development 和 production,方便开发者在项目业务代码中判断当前构建模式。
  • production 模式会启用TerserPlugin来压缩JS代码,让生成的代码文件更小。
  • development 模式会启用 devtools: ‘eval’ 配置,提升构建和再构建的速度。
    在这里插入图片描述

前端构建基础配置

关联HTML插件html-webpack-plugin

webpack4.x对应的html-webpack-plugin@4

npm install html-webpack-plugin@4 -D 

webpack配置:

const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html'
    }),
  ]
}

构建 CSS

webpack4.x安装style-loader2.x、css-loader3.x

安装:

npm i css-loader@3 style-loader@2 -D

配置中引入 loader 来解析和处理 CSS 文件:

module: {
    rules: [
      {
        test: /\.css$/,
        include: [path.resolve(__dirname, 'src')],
        use: ['style-loader', 'css-loader'],
      }
    ]
}
  • css-loader 负责解析 CSS 代码,主要是为了处理 CSS 中的依赖,例如 @import 和 url() 等引用外部文件的声明;
  • style-loader 会将 css-loader 解析的结果转变成 JS 代码,运行时动态插入 style 标签来让 CSS 代码生效。

如果需要单独把 CSS 文件分离出来,我们需要使用 mini-css-extract-plugin 插件。

注:v4 版本之后才开始使用 mini-css-extract-plugin,之前的版本是使用 extract-text-webpack-plugin。

安装mini-css-extract-plugin插件:

npm i mini-css-extract-plugin -D

配置:

解析 ES6和React JSX

解析 ES6

webpack4.x安装@babel/core,@babel/preset-env,babel-loader@8

npm i @babel/core @babel/preset-env babel-loader@8 -D

在根路径下新建一个.babelrc文件,增加ES6的babel preset配置,代码如下:

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

webpack.config.js配置:

module: {
    rules: [
      {
        test: /\.js$/,
        use: 'babel-loader'
      } 
    ]
}

解析 React JSX

安装:

npm i @babel/preset-react -D
npm i react react-dom -S

在.babelrc文件中添加react相关配置:

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

编写一个示例代码JS,例如src/search.js:

'use strict'

import React from 'react'
import ReactDOM from 'react-dom'

class Search extends React.Component {
  render() {
    return <div>Search Text</div>
  }
}

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

然后编译后 引用编译后的JS查看效果即可。其中在dist中编写的search.html示例需要添加root这个dom节点。

解析CSS、Less和Sass

解析CSS

解析css,需要安装style-loadercss-loader

其中webpack4.x安装style-loader2.xcss-loader3.x:

npm i css-loader@3 style-loader@2 -D

版本参考:https://github.com/webpack-contrib/style-loader/blob/v2.0.0/package.json

rules配置:

{
    test: /.css$/,
    use: ['style-loader', 'css-loader']
}

解析Less

解析less,需要安装less、less-loader。

其中webpack4.x建议安装less-loader@6(less-loader@7.0.1也支持webpack4.x)

npm i less less-loader@6 -D

版本参考:https://github.com/webpack-contrib/less-loader/blob/v6.2.0/package.json

rules配置如下:

{
    test: /.less$/,
    use: ['style-loader', 'css-loader', 'less-loader']
}

解析sass

webpack4.x安装依赖:

npm i sass-loader@7.3.1 node-sass@4.14.1 sass-resources-loader@2 sass-resources-loader@2.2.4 -D

element-ui依赖的sass-loder跟node-sass版本:

npm i sass-loader@10.2.0  sass@1.29.0 -D

rules配置:

{
    test: /.scss$/,
    use: ['style-loader', 'css-loader','sass-loader']
}

解析图片和字体

资源解析:解析图片

解析图片,可以安装file-loader,其中file-loader最新版本为6.2.0,支持webpack4.x。

npm i file-loader -D

版本参考:https://github.com/webpack-contrib/file-loader/blob/v6.2.0/package.json

rules配置如下:

{
    test: /.(png|jpe?g|gif)$/,
    use: 'file-loader'
}

资源解析:解析字体

rules配置如下:

{
    test: /.(woff|woff2|eot|otf|ttf)$/,
    use: 'file-loader'
},

css参考样式:

@font-face {
  font-family: 'SourceHeavy';
  src: url('./images/SourceHeavy.otf') format('truetype');
}

.search-text {
  font-size: 20px;
  color: #f00;
  font-family: 'SourceHeavy';
}

资源解析:使用url-loader

url-loader 也可以处理图⽚和字体,可以设置较⼩资源⾃动 base64,其中url-loader内部实现也是使用的file-loader。

目前url-loader最新版本为4.1.1,支持webpack4.x.

npm i url-loader -D

版本参考:https://github.com/webpack-contrib/url-loader/blob/master/package.json

rules配置(把之前关于图片的file-loader配置替换):

 {
    test: /.(png|jpe?g|gif)$/,
    use: [{ loader: 'url-loader', options: { limit: 10240 } }],
 }

webpack中的文件监听

⽂件监听是在发现源码发⽣变化时,⾃动重新构建出新的输出⽂件。

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

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

在package.json中添加命令如下:

  "scripts": {
    "watch": "webpack --watch"
  },

注:唯⼀缺陷:每次需要⼿动刷新浏览器。

⽂件监听的原理分析:

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

某个⽂件发⽣了变化,并不会⽴刻告诉监听者,⽽是先缓存起来,等 aggregateTimeout

module.export = {
    //默认 false,也就是不开启
    watch: true,
    //只有开启监听模式时,watchOptions才有意义
    wathcOptions: {
    //默认为空,不监听的文件或者文件夹,支持正则匹配
    ignored: /node_modules/,
    //监听到变化发生后会等300ms再去执行,默认300ms
    aggregateTimeout: 300,
    //判断文件是否发生变化是通过不停询问系统指定文件有没有变化实现的,默认每秒问1000次
    poll: 1000
    }
}

webpack中的热更新及原理分析

热更新:webpack-dev-server

  • webpack-dev-server不刷新浏览器
  • webpack-dev-server不输出⽂件,⽽是放在内存中
  • 使⽤ HotModuleReplacementPlugin插件

webpack4.x对应安装的webpack-dev-server版本3.x。

npm i webpack-dev-server@3 -D

package.json配置:

"scripts": {
    "dev": "webpack-dev-server --open"
}

其中open是构建完成之后,自动开启浏览器。

在webpack.config.js配置:

'use strict'

const webpack = require('webpack');

module.exports = {
  // 其他省略
  mode: 'development',
  plugins: [new webpack.HotModuleReplacementPlugin()],
  devServer: {
    contentBase: './dist',
    hot: true
  }
}

热更新的原理分析:
在这里插入图片描述

  • Webpack Compile:将JS编译成Bundle
  • HMR Server: 将热更新的⽂件输出给HMR Rumtime Bundle server: 提供⽂件在浏览器的访问
  • HMR Rumtime: 会被注⼊到浏览器,更新⽂件的变化
  • bundle.js: 构建输出的⽂件

热更新:使⽤ webpack-dev-middleware

  • WDM 将 webpack 输出的⽂件传输给服务器
  • 适⽤于灵活的定制场景

示例:

const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const app = express();
const config = require('./webpack.config.js');
const compiler = webpack(config);

app.use(webpackDevMiddleware(compiler, {
    publicPath: config.output.publicPath
}));
app.listen(3000, function () {
    console.log('Example app listening on port 3000!\n');
});

文件指纹策略:chunkhash、contenthash和hash

注:文件指纹只能用于生产环境。

文件指纹如何生成

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

文件指纹设置

  • JS文件:设置output的filename,使⽤[chunkhash]。
output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name]_[chunkhash:8].js'
  }
  • CSS文件:设置MiniCssExtractPlugin的filename,使⽤[contenthash]

webpack4.x安装的mini-css-extract-plugin@1.0.0

npm i mini-css-extract-plugin@1.0.0 -D

配置:

const MiniCssExtractPlugin = require('mini-css-extract-plugin')

module.exports = {
  // 其他省略
  mode: 'production',
  module: {
    rules: [
     
      {
        test: /.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader'],
      },
      {
        test: /.less$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader'],
      }
    ]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name]_[contenthash:8].css',
    }),
  ],
}


插件参考地址:https://github.com/webpack-contrib/mini-css-extract-plugin/blob/v1.0.0/package.json

  • 图片文件:设置file-loader的name,使⽤[hash]
const MiniCssExtractPlugin = require('mini-css-extract-plugin')

module.exports = {
  // 其他省略
  mode: 'production',
  module: {
    rules: [
      {
        test: /.(png|jpe?g|gif)$/,
        use: [
          {
            loader: 'file-loader',
            options: { name: '[name]_[hash:8].[ext]' },
          },
        ],
      },
      {
        test: /.(woff|woff2|eot|otf|ttf)$/,
        use: [
          {
            loader: 'file-loader',
            options: { name: '[name]_[hash:8].[ext]' },
          },
        ]
      }
    ]
  }
}

HTML 、CSS和JavaScript代码压缩

JS压缩

webpack4及以后内置了uglifyjs-webpack-plugin

CSS压缩

需要安装optimize-css-assets-webpack-plugin,同时使⽤cssnano

说明:optimize-css-assets-webpack-plugin插件目前官网最新版本5.0.8,使用的webpack为^4.44.1。

npm i optimize-css-assets-webpack-plugin@5 cssnano@4 -D

插件配置地址:https://github.com/NMFR/optimize-css-assets-webpack-plugin/blob/master/package.json

const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')

module.exports = {
  // 其他省略
  mode: 'production',
  plugins: [
    new OptimizeCssAssetsPlugin({
      assetNameRegExp: /\.css$/g,
      cssProcessor: require('cssnano'),
    }),
  ],
}

HTML压缩

安装html-webpack-plugin,并设置压缩参数。

其中webpack4.x对应的html-webpack-plugin@4。

npm i html-webpack-plugin@4 -D

webpack配置:

const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  
  plugins: [
    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,
      },
    }),

    new HtmlWebpackPlugin({
      template: path.join(__dirname, 'src/search.html'),
      filename: 'search.html',
      chunks: ['search'],
      inject: true,
      minify: {
        html5: true,
        collapseWhitespace: true,
        preserveLineBreaks: false,
        minifyCSS: true,
        minifyJS: true,
        removeComments: false,
      },
    }),
  ],
}

webpack.dev.js完整配置:

'use strict'

const path = require('path')
const webpack = require('webpack')

module.exports = {
  entry: {
    index: './src/index.js',
    search: './src/search.js',
  },
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name].js',
  },
  mode: 'development',
  module: {
    rules: [
      {
        test: /.js$/,
        use: 'babel-loader',
      },
      {
        test: /.css$/,
        use: ['style-loader', 'css-loader'],
      },
      {
        test: /.less$/,
        use: ['style-loader', 'css-loader', 'less-loader'],
      },
      {
        test: /.(png|jpe?g|gif)$/,
        use: [{ loader: 'url-loader', options: { limit: 10240 } }],
      },
      {
        test: /.(woff|woff2|eot|otf|ttf)$/,
        use: 'file-loader',
      },
    ],
  },
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    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,
      },
    }),

    new HtmlWebpackPlugin({
      template: path.join(__dirname, 'src/search.html'),
      filename: 'search.html',
      chunks: ['search'],
      inject: true,
      minify: {
        html5: true,
        collapseWhitespace: true,
        preserveLineBreaks: false,
        minifyCSS: true,
        minifyJS: true,
        removeComments: false,
      },
    }),
  ],
  devServer: {
    contentBase: './dist',
    hot: true,
  },
}

webpack.prod.js完整配置:

'use strict'

const path = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  entry: {
    index: './src/index.js',
    search: './src/search.js',
  },
  output: {
    path: path.join(__dirname, 'dist'),
    filename: '[name]_[chunkhash:8].js',
  },
  mode: 'production',
  module: {
    rules: [
      {
        test: /.js$/,
        use: 'babel-loader',
      },
      {
        test: /.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader'],
      },
      {
        test: /.less$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader'],
      },
      {
        test: /.(png|jpe?g|gif)$/,
        use: [
          {
            loader: 'file-loader',
            options: { name: '[name]_[hash:8].[ext]' },
          },
        ],
      },
      {
        test: /.(woff|woff2|eot|otf|ttf)$/,
        use: [
          {
            loader: 'file-loader',
            options: { name: '[name]_[hash:8].[ext]' },
          },
        ],
      },
    ],
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name]_[contenthash:8].css',
    }),
    new OptimizeCssAssetsPlugin({
      assetNameRegExp: /\.css$/g,
      cssProcessor: require('cssnano'),
    }),

    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,
      },
    }),

    new HtmlWebpackPlugin({
      template: path.join(__dirname, 'src/search.html'),
      filename: 'search.html',
      chunks: ['search'],
      inject: true,
      minify: {
        html5: true,
        collapseWhitespace: true,
        preserveLineBreaks: false,
        minifyCSS: true,
        minifyJS: true,
        removeComments: false,
      },
    }),
  ],
}

package.json:

{
  "name": "webpacktest",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "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"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/core": "^7.22.10",
    "@babel/preset-env": "^7.22.10",
    "@babel/preset-react": "^7.22.5",
    "babel-loader": "^8.3.0",
    "css-loader": "^3.6.0",
    "cssnano": "^4.1.11",
    "file-loader": "^6.2.0",
    "html-webpack-plugin": "^4.5.2",
    "less": "^4.2.0",
    "less-loader": "^6.2.0",
    "mini-css-extract-plugin": "^1.0.0",
    "optimize-css-assets-webpack-plugin": "^5.0.8",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "style-loader": "^2.0.0",
    "url-loader": "^4.1.1",
    "webpack": "^4.46.0",
    "webpack-cli": "^3.3.12",
    "webpack-dev-server": "^3.11.3"
  }
}

.babelrc配置:

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2139281.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

系统 IO

"裸奔"层次&#xff1a;不带操作系统的编程 APP(应用程序) -------------------------------- Hardware(硬件) 特点&#xff1a;简单&#xff0c;应用程序直接操作硬件(寄存器) 缺点&#xff1a; 1. 搞应用开发的必须要了解硬件的实现细节&#xff0c;能够看懂原理图…

Depth靶机详解

靶机下载地址 https://www.vulnhub.com/entry/depth-1,213/ 主机发现 arp-scan -l 端口扫描 nmap -sV -A -T4 192.168.229.156 端口利用 http://192.168.229.156:8080/ 目录扫描 dirb "http://192.168.229.156:8080" dirsearch -u "http://192.168.229.15…

UDP_SOCKET编程实现

文章目录 socket编程接口认识struct sockaddr类 编写一个server服务Client代码查看启动结果代码修正1.获取内核分配给客户端的信息2.修正不匹配ip不能访问的问题 不同机器之间的通信利用xftp将udp_client传给wsl的ubuntu机器进行演示现在模拟在windows下的udp_client代码: 对方…

松材线虫多光谱数据集

松材线虫多光谱数据集 无人机&#xff1a;dji mavic3 mutispectral 波段&#xff1a;red green rededge nir rgb 面积&#xff1a;39.05平方公里 数据&#xff1a;rgb影像&#xff0c;四个单波段影像&#xff0c;NDVI GNDVI LCI NDRE OSAVI 5个指数图 分辨率&#xff1a;0.03&a…

【智路】智路OS 欢迎来到智路OS路侧操作系统开发手册

https://airos-edge.readthedocs.io/zh/latest/ 欢迎来到智路OS路侧操作系统开发手册 智路OS 是一套完整的软件和服务开放系统&#xff0c; 由路侧操作系统&#xff08;airos-edge&#xff09;&#xff0c;车端&#xff08;airos-vehicle&#xff09;和云端开发者平台共同构成…

【Spring Boot】SpringBoot自动装配-Import

目录 一、前言二、 定义三、使用说明3.1 创建项目3.1.1 导入依赖3.1.2 创建User类 3.2 测试导入Bean3.2.1 修改启动类 3.3 测试导入配置类3.3.1 创建UserConfig类3.3.2 修改启动类 3.4 测试导入ImportSelector3.4.1 创建UseImportSelector类3.4.2 修改启动类3.4.3 启动测试 3.5…

Python 二维码(QR码)生成器:使用python-qrcode简化条码创建

在数字时代&#xff0c;QR码已成为快速信息共享和数据传输的必备工具。无论是用于市场营销活动、活动签到&#xff0c;还是仅仅分享Wi-Fi凭证&#xff0c;QR码都提供了一种方便的方式来打包和扫描访问信息。今天&#xff0c;我们将探索python-qrcode库&#xff0c;这是一个强大…

Golang | Leetcode Golang题解之第409题最长回文串

题目&#xff1a; 题解&#xff1a; func longestPalindrome(s string) int {mp : map[byte]int{}for i : 0; i < len(s); i {mp[s[i]]}res : 0for _, v : range mp {if v&1 1 {res v - 1} else {res v}}if res<len(s) {res}return res }

【MyBatis精讲】从入门到精通的详细指南:简化Java持久层操作的艺术

文章目录 【MyBatis精讲】从入门到精通的详细指南&#xff1a;简化Java持久层操作的艺术1.mybatis快速入门1.1创建步骤1.2mapper代理开发模式 2.mybatis增删改查2.1查询所有数据2.2 id查询数据2.3插入数据2.4修改数据2.5删除数据2.6 mybatis多条件查询2.7 mybatis动态条件查询 …

HTML标签优先级

HTML&#xff08;HyperText Markup Language&#xff09;标签的位置对于页面的结构、性能以及可维护性至关重要。合理安排标签的位置不仅有助于提高网页的加载速度&#xff0c;还能使得代码更加清晰易懂。以下是一些关于HTML标签放置的基本规则和建议&#xff1a; 1. 文档类型…

web安卓逆向之必学HTML基础知识

文章目录 HTML基础知识一、HTML的介绍1. HTML定义2. HTML 的作用1. 定义网页的结构2. 实现超文本链接3. 支持多媒体内容4. 提供表单交互5. 提高网页的可访问性和 SEO 3. 小结 二、html的基本结构1. HTML 基本结构2. HTML 基本结构的详细介绍3. 教学案例4. 补充知识5. 小结 三、…

【网络通信基础与实践第三讲】传输层协议概述包括UDP协议和TCP协议

一、进程间的通信 通信的两端应当是两个主机中的应用进程&#xff0c;也就是说&#xff0c;端到端的通信是应用进程之间的通信 运输层有一个很重要的功能就是复用和分用&#xff0c;复用是指在发送方不同的应用进程都可以使用同一个运输层协议传送数据&#xff0c;分用是指接…

C++前后缀分解

相关知识点 C算法与数据结构 打开打包代码的方法兼述单元测试 这个算法很容易想到&#xff0c;学习了本文后&#xff0c;可以更快得想到。 前后缀分解 分治法的一种&#xff0c;将数组和字符串&#xff0c;拆分成前缀和后缀。字符串(数组&#xff09;的前缀是字符串的前i个元…

QT模型视图结构2

文章目录 Qt 模型视图结构——模型类(二)1.基本概念1.1.模型的基本结构1.2.模型索引1.3.行号和列号1.4.父项1.5.项的角色 Qt 模型视图结构——模型类(二) ​ 模型/视图结构是一种将数据存储和界面展示分离的编程方法。模型存储数据&#xff0c;视图组件显示模型中的数据&#…

ChatGPT提示词-中文版(awesome-chatgpt-prompts中文版)

原是Github上110.6K星的项目&#xff1a;GitHub - f/awesome-chatgpt-prompts: This repo includes ChatGPT prompt curation to use ChatGPT better. 我翻译成了中文需要自提 我用夸克网盘分享了「Chat GPT提示词.csv」&#xff0c;点击链接即可保存。打开「夸克APP」在线查看…

Windows11 WSL2的ubuntu 22.04中拉取镜像报错

问题描述 在windows11 WSL2的ubuntu 22.04中拉取镜像报错。错误为&#xff1a; Error response from daemon: Get "https://registry-1.docker.io/v2/": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting header…

深度学习的关键数据结构——张量解释

参考英文文章: https://deeplizard.com/learn/video/Csa5R12jYRghttps://deeplizard.com/learn/video/Csa5R12jYRg 什么是张量&#xff08;Tensor&#xff09; 神经网络中的输入、输出和变换都是用张量表示的&#xff0c;因此&#xff0c;神经网络编程大量使用张量。张量的概念…

【资料分析】特殊考点——拉动增长、贡献率、容斥问题

拉动增长和增量贡献率 第X产业增加值 是一个整体名称&#xff0c;例如张狗剩这是一个整体的名字 增量贡献率 部分增量/ 整体增量&#xff0c;已知增量贡献率80.6%,对应的部分增量可以求得&#xff08;现期2632&#xff0c;增长率10.3%&#xff0c;可用假设分配&#xff09;&a…

【Linux 20】进程控制

文章目录 &#x1f308; 一、创建线程⭐ 1. 线程创建函数⭐ 3. 给线程传参⭐ 4. 创建多线程⭐ 5. 获取线程 ID &#x1f308; 二、终止线程⭐1. 使用 return 终止线程⭐ 2. 使用 pthread_exit 函数终止线程⭐ 3. 使用 pthread_cancel 函数终止线程 &#x1f308; 三、等待线程⭐…

如何查看串口被哪个程序占用?截止目前最方便的方法

痛点&#xff1a;串口因为某种原因被占用&#xff0c;如何找到罪魁祸首&#xff1f; 做开发的小伙伴们&#xff0c;经常会遇到这样的问题&#xff1a;串口因为某种原因被占用&#xff0c;导致无法通讯&#xff0c;但是又找不到被哪个程序占用。只有重启电脑&#xff0c;才能解…