• webpack4配置基础


    前言

    为什么要使用构建工具?

    1.转换ES6语法(很多老版本的浏览器不支持新语法) 2.转换JSX  3.CSS前缀补全/预处理器  4.压缩混淆(将代码逻辑尽可能地隐藏起来)  5.图片压缩  6. ....

    为什么选择webpack?

    1. 社区生态丰富
    2. 配置灵活、插件化扩展
    3. 官方更新迭代速度快

    基础概念

    默认的配置文件是weback.config.js,在package.json中配置脚本可以通过webpack --config来指定构建使用的配置文件。

    初始化

    创建并进入新的目录,执行如下命令,初始化package.json文件,这是一个模块的描述文件,-y的意思是所有配置都是yes

    npm init -y

    安装webpack

    npm install webpack webpack-cli --save-dev

    核心概念

    先看一下一份最简单的webpack配置是什么样的

    const path = require('path');
    
    module.exports = {
       entry: './src/index.js',  // 打包的入口文件
       output: {    // 打包后的输出
          filename: "bundle.js",
          path: path.join(__dirname, "/dist")
       },
       mode: 'development', // 所处环境
       module: {
          rules: [
             {
                test: /.js$/,
                use: "babel-loader"
             },
             ......
          ]
       },
       plugins: [
          new HtmlWebpackPlugin(),
       ]
    };

    entry

    打包的入口文件 

    单入口:

    entry: "./src/index.js"

    多入口(适用于多页面场景):

    entry: {
        app: "./src/app.js",
        adminApp: "./src/adminApp.js",
    }

    output

    打包之后的输出

    单输出:

    output: {
        filename: "bundle.js",
        path: __dirname + "/dist" 
    }

    多输出:

    output: {
        filename: "[name].js", // 占位符[name]代表entry中的key
        path: __dirname + "/dist"
    }

    Loaders

    webpack只支持JS和JSON两种文件类型,要想支持其他文件类型且转化成有效的模块,需要通过Loaders。Loaders本身是一个函数,接收源文件做参数,返回转换的结果。

    常见的Loaders

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

    Plugins

    插件用于打包文件的优化,资源管理和环境变量注入,作用于整个构建过程。也可以理解为Loaders无法完成的事情都可以用Plugins完成。

    常见的Plugins:

    CommonsChunkPlugin        常用于多页面打包情况下,将多个页面公用的js代码块提取成公共js
    CleanWebpackPlugin        清理构建目录
    ExtractTextWebpackPlugin  将CSS从bundle文件里提取成一个独立的CSS文件
    CopyWebpackPlugin         将文件或文件夹拷贝到够贱的输出目录
    HtmlWebpackPlugin         创建html文件去承载输出的bundle。这个非常有用,不需要我们手动去创建html文件
    UglifyjsWebpackPlugin     压缩JS
    ZipWebpackPlugin          将打包的资源生成一个zip包

    mode

    用来指定当前的构建环境,值有 production 、development 、none,默认是production。通过mode可以使用webpack内置的函数和功能:

    developement

    开启 NamedChunksPlugin 和 NamedModulesPlugin 在代码热更新阶段,打印哪个模块发生了更新

    production

    开启 FlagDependencyUsagePlugin , FlagIncludedChunksPlugin , ModuleConcatenationPlugin , NoEmitOnErrorsPlugin,OccurrenceOrderPlugin , SideEffectsFlagPlugin 和 TerserPlugin

    none

    不开启任何优化

    webpack基础功能

    解析ES6

    使用babel-loader, babel的配置文件是.babelrc, 增加ES6的babel preset配置

    1.安装包

    npm install @babel/core @babel/preset-env babel-loader -D

    2.创建.babelrc文件,并添加配置

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

    3.webpack.config.js配置

    module: {
          rules: [
             {
                test: /.js$/,
                use: "babel-loader", // 用来解析ES6
             },
          ]
    },

    解析JSX

    增加babel preset配置:

    "@babel/preset-react"

    要在React中使用箭头函数,需要安装插件

    npm i @babel/plugin-proposal-class-properties
    // .babelrc
    "plugins": [
        "@babel/plugin-proposal-class-properties"
    ]

    解析CSS/CSS预处理/前缀补全

    less-loader   将less转化成css
    css-loader    让webpack解析css文件,并转换成commonjs对象,插入到JS里(因为webpack本身只支持js和json)
    style-loader  将样式通过<style>标签插入到<head>中

    CSS前缀常见的有: -ms -moz -webkit -o 需要安装autoprefixer 和 postcss-loader

    npm i autoprefixer postcss-loader

    配置:

    {
       test: /.less$/,
       use: [
          "style-loader",
          "css-loader",
          {
             loader: "postcss-loader",
             options: {
                plugins: () => [
                   require('autoprefixer')({
                      overrideBrowserslist: ['last 2 version', '>1%', 'ios 7'] // 指定所需要兼容浏览器的版本
                   })
                ]
             }
          },
          "less-loader",
       ]
    },
    执行顺序:less-loader -> postcss-loader -> css-loader -> style-loader

    解析图片、字体

    file-loader 用于处理文件

     js文件中:

    import logo from './images/geektime.png'
    const MyComponent = () => {
        retrun <img alt="" src={logo} />
    }

    webpack.config.js配置:

    {
       test: /.(png|jpg|gif|jpeg)$/i,
       use: {
          loader: "file-loader",
          options: {
             name: '[name][hash:8].[ext]'  // 重命名打包后的文件
          }
       }
    }

    很多时候,前端的图片请求路径需要从后端接口获取,不适用此场景。另外,即使不从后端获取,静态资源也可以用传统的相对路径引用,此时存在一个问题,就是打包后的文件夹,与打包前源文件位置不同,相对静态文件的相对路径也不同,造成打包后路径失效,无法引入的情况。我们需要将静态文件夹整体复制到打包后的文件目录内,手工做太麻烦,可以借助插件实现。

    npm i copy-webpack-plugin

     webpack.config.js配置:

    const CopyWebpackPlugin = require('copy-webpack-plugin');
    plugins: [
          new CopyWebpackPlugin([
             {
                from: './src/static',
                to: __dirname + './dist/static'
             }
          ])
    ]

    资源解析

    url-loader 也可以处理图片和字体,可以设置较小资源自动 base64。

    webpack.config.js配置:

    {
       test: /.(png|svg|jpg|gif)$/,
       use: [
          {
             loader: "url-loader",
             options: {
                limit: 1024*5,  // 当文件小于1024*n字节,webpack将该资源自动转化成base64编码在js文件中
             }
          }
       ]
    }

    文件监听

    文件监听指在发现源代码发生变化时,自动重新构建出新的输出文件。需要手动刷新浏览器。

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

    • 命令打包时带上 --watch参数(可以在package.json中配置脚本)
    • 配置webpack.config.js中设置 watch: true

    webapck配置:

    watch: true,
    watchOptions: {
       ignored: /node_modules/,   // 不监听的文件或文件夹,默认为空。正则匹配/字符串都可
       aggregateTimeout: 300,     // 监听到变化发生后,延迟300ms再去执行,默认300ms
       poll: 1000              // 轮询频率,默认每秒1000次
    },

    监听原理:轮询判断文件的最后编辑时间是否发生变化。某个文件发生了变化,并不会立即告诉监听者,而是先缓存起来,等aggregateTimeout时间过后再构建。

    热更新

    需要安装webpack-dev-server,适用于开发环境,不输出文件,将构建后的内容保存在内存中。

    在package.json中编写脚本:

    "dev": "webpack-dev-server --open"   // open指自动打开浏览器

    webpack配置:

    devServer: {
       contentBase: './dist',   // 必需
       port: 8080,  // 默认8080
       hot: true   // 默认true
    },

    当然,如果使用html-webpack-plugin,则不需要contentBase属性。

    文件指纹策略

    作用:

    1. 做版本管理。当文件发生修改时,只需要更新发生变化的文件
    2. 浏览器缓存。文件名发生变化时,浏览器会重新请求该文件,而其它未改变的文件则直接从缓存中拿就行。

    三种hash:

    • Hash:和整个项目的构建相关,只要项目文件有修改,整个项目构建的hash值就会改变
    • Chunkhash:和webpack打包的chunk有关,不同的entry会生成不同的chunkhash值,只能在生产环境中使用
    • Contenthash:根据文本内容来定义hash,文件内容不变,则contenthash不变

    使用:

    entry: {
        app: './src/app.js',
        search: './src/search.js',
    },
    output: {
        filename: '[name][chunkhash:8].js', 
        path: __dirname + '/dist'
    }

    CSS由于style-loader的存在,被内联在html中,可以用插件将其独立出一个css文件。

    npm install mini-css-extract-plugin
    
    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    plugins: [
        new MiniCssExtractPlugin({ // 该插件会将css提取出来并在html中引入独立的文件,与style-loader互斥
            filename: '[name][contenthash:8].css'
        });
    ]

    JS文件只能使用hash和ChunkHash,CSS建议使用ContentHash

    占位符:
    [ext]   后缀名
    [name]  文件名称
    [path]  文件的相对路径
    [folder] 文件所在的文件夹
    [contenthash]  文件的内容hash,默认是md5生成
    [hash]      文件内容的hash,默认md5生成(注意这里的hash与前面的"hash"意义不一样)
    [emoji]     一个随机的只带文件内容的emoji

    文件压缩

    主要是HTML、CSS、JS的压缩

    JS压缩:

      webpack内置了uglifyjs-webpack-plugin,在生产环境自动实现了JS压缩

    CSS压缩:

      使用optimize-css-assets-webpack-plugin 和 cssnano可以实现对CSS文件进行压缩,因为style-loader将CSS内联在html中,需要借助 mini-css-extract-plugin 插件将CSS分离成文件。

    HTML压缩:

      html-webpack-plugin设置压缩参数minify,可以将空格、换行和注释干掉

    npm install html-webpack-plugin optimize-css-assets-webpack-plugin cssnano mini-css-extract-plugin
    
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const MiniCssExtractPlugin = require('mini-css-extract-plugin');
    const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
    // 一个页面对应一个 html-webpack-plugin
    module: {
          rules: [
             {
                test: /.less$/,
                use: [
                   // "style-loader",
                   MiniCssExtractPlugin.loader, // 与style-loader互斥
                   "css-loader",
                   {
                      loader: "postcss-loader",
                      options: {
                         plugins: () => [
                            require('autoprefixer')({
                               overrideBrowserslist: ['last 2 version', '>1%', 'ios 7'] // 指定所需要兼容浏览器的版本
                            })
                         ]
                      }
                   },
                   "less-loader",
                ]
             },
          ]
    },
    new HtmlWebpackPlugin({
       template: "./src/index.html", // 模板所在路径
       filename: "index.html", // 指定打包后的文件名称
       // chunks: [''], // 生成的html要链入哪些js文件。数组值对应的是entry中的键
       // inject: true,  // 将生成的css等文件自动注入到html内,默认开启
       minify: {
          html5: true,
          collapseWhitespace: true,   // 干掉空格
          preserveLineBreaks: false,  // 干掉换行
          minifyCSS: true,      // 压缩html内的css
          minifyJS: true,       // 压缩html内的js
          removeComments: true, // 删除注释
       },
    }),
    new MiniCssExtractPlugin({
       filename: '[name][contenthash:8].css'
    }),
    new OptimizeCssAssetsPlugin({
       assetNameRegExp: /.css$/g,
       cssProcessor: require('cssnano'),
    }),

    自动清理构建目录

    借助 clean-webpack-plugin 每次构建都会自动删除之前的构建目录。默认会删除output指定的输出目录。

    const { CleanWebpackPlugin } = require('clean-webpack-plugin');
    new CleanWebpackPlugin(),
  • 相关阅读:
    项目中libevent几个问题
    Initialization of bean failed; nested exception is org.springframework.beans.InvalidPropertyException: Invalid property 'dataSource' of bean class [com.liuyang.jdbc.PersonDao]: No property 'dataSource
    Can not issue data manipulation statements with executeQuery().
    Caused by: java.lang.IllegalArgumentException: error at ::0 can't find referenced pointcut aaa
    VMware + LInux + Xshell 连接环境设置(心得体会)
    对于Serializable id类型的数据的测试
    SessionCacheTest03.testLoad Unrooted Tests initializationError
    java.lang.NoClassDefFoundError: org/hamcrest/SelfDescribing,
    java.lang.ExceptionInInitializerError Caused by: org.hibernate.InvalidMappingException: Unable to read XML
    Caused by: org.hibernate.InvalidMappingException: Could not parse mapping document from resource Caused by: org.hibernate.DuplicateMappingException: duplicate import: Person refers to both cn.itcast.
  • 原文地址:https://www.cnblogs.com/V587Chinese/p/11555241.html
Copyright © 2020-2023  润新知