Webpack HTML的打包编译+自定义打包规则

255 阅读3分钟

image.png

image.png

keyword

插件 加载器 跨域 兼容

webpack.config.js

const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin')
const TerserPlugin = require('terser-webpack-plugin')

module.exports = {
  /* 基础配置 */
  mode: 'production',
  entry: './src/index.js',
  output: {
    filename: '[name].[hash:8].js',
    path: path.resolve(__dirname, './dist'),
  },
  /* 优化项 */
  optimization: {
    // 设置压缩方式
    minimizer: [
    new CssMinimizerWebpackPlugin(), 
    // ts压缩
    new TerserPlugin()
  ],},
  /* 使用插件 */
  plugins: [
    new HtmlWebpackPlugin({
      template: './public/index.html',
      filename: 'index.html',
      minify: true,
    }),
    // 清除之前打包的内容
    new CleanWebpackPlugin(),
    // 抽离CSS样式
    new MiniCssExtractPlugin({
      // 打包后CSS文件的名字
      filename: 'main.[hash:8].css',
    }),
  ],
  /* DEV-SERVER */
  devServer: {
    host: '127.0.0.1', //域名
    port: 3000, //端口号
    open: true, //自动打开浏览器
    hot: true, //热更新
    compress: true, //开启服务器端的GZIP压缩
    /* 
         跨域代理的处理  
           "/xxx" 前缀:主要就是用来区分,以“什么前缀”发的请求,我们代理到哪一台服务器上 「一般设置为"/api"」
           target:代理的真正服务器地址
           pathRewrite:地址重写,主要用于把用来区分不同代理的前缀,从最后请求的真正地址中移除掉
           changeOrigin:修改请求头中的origin源信息
           ws:支持webscoket通信机制
        */
    proxy: {
      '/jian': {
        target: 'https://www.jianshu.com/asimov',
        changeOrigin: true,
        ws: true,
        pathRewrite: { '^/jian': '' },
      },
      '/zhi': {
        target: 'https://news-at.zhihu.com/api/4',
        changeOrigin: true,
        ws: true,
        pathRewrite: { '^/zhi': '' },
      },
    },
  },
  /* LOADER加载器:执行顺序 下->上、右->左 */
  module: {
    rules: [
      {
        test: /\.(css|less)$/, //基于正则匹配:哪些文件是我们需要处理的
        use: [
          MiniCssExtractPlugin.loader, //抽离CSS代码的
          // "style-loader", //把CSS以内嵌式导入到页面
          'css-loader', //处理特殊语法
          'postcss-loader', //配合autoprefixer&browserslist给CSS3属性设置前缀「兼容」
          'less-loader', //把less编译为css
        ],
      },
      {
        test: /\.js$/,
        use: ['babel-loader'],
        // 设置编译时忽略的文件和指定编译目录「优化处理」
        // include: path.resolve(__dirname, 'src'),
        exclude: /node_modules/,
      },
      {
        test: /\.(png|jpe?g|gif)$/i,
        type: 'javascript/auto', //webpack5需要的
        use: [
          {
            loader: 'url-loader',
            options: {
              // 把指定大小内的图片BASE64「<=200KB则需要BASE64」
              limit: 200 * 1024,
              esModule: false,
              // 编译后,没有BASE64的图片,编译输出的路径和名称
              name: 'images/[name].[hash:8].[ext]',
            },
          },
        ],
      },
    ],
  },
  /* 设置打包的最大资源大小 */
  performance: {
    maxAssetSize: 100 * 1024 * 1024,
    maxEntrypointSize: 100 * 1024 * 1024,
  },
  /* 解析器 */
  resolve: {
    alias: {
      // @以后代表的就是SRC这个路径
      '@': path.resolve(__dirname, './src'),
    },
  },
}
fetch('/jian/subscriptions/recommended_collections')
  .then((response) => response.json())
  .then((value) => {
    console.log('简书:', value)
  })
fetch('/zhi/news/latest')
  .then((response) => response.json())
  .then((value) => {
    console.log('知乎', value)
  })

浏览器兼容处理

考虑CSS3样式的兼容问题

  • postcss-loader & autoprefixer

  • 根据browserslist,自动给CSS3加相关的前缀

考虑JS的兼容性

  • ES6+语法兼容:把ES6+语法转换为ES5的语法

    • babel & babel-loader & @babel/preset-env & @babel/core & browserslist
  • ES6+内置API的兼容:上述操作处理不了,需要导入@babel/polyfill

    • 对常见的内置API进行了重写,不是所有API都重写了,fetch/Reflect等就没有重写!!

index.js

/* 处理ES6内置API的兼容 */
import '@babel/polyfill'

/* 项目中需要用到的CSS,我们在入口中基于模块规范导入进来 */
import '@/assets/css/reset.min.css'
import '@/index.less'

import sum from '@/A'
import average from '@/B'
console.log(sum(10, 20, 30, 40, 50))
console.log(average(10, 20, 30, 40))

/* 先页面中动态插入图片 */
// JS中处理静态图片,需要先基于ES6Module规范导入进来「这样webpack才会对此图片进行打包」
// 如果写的是相对地址,打包后还是这个地址,但是打包后的资源路径全都变了「不是SRC这样的路径了」,所以肯定找不到图片;但是设置的是绝对地址(外部网址那种的),无需先import导入,直接写地址即可{无需经过webpack打包}!!
import temp from '@/assets/images/boy.jpg'
let img = new Image()
img.src = temp
document.body.appendChild(img)

/* new Promise(() => { }); */

// fetch('/jian/subscriptions/recommended_collections')
//   .then((response) => response.json())
//   .then((value) => {
//     console.log('简书:', value)
//   })
// fetch('/zhi/news/latest')
//   .then((response) => response.json())
//   .then((value) => {
//     console.log('知乎', value)
//   })

自定义打包规则

  • 基础配置
  • HtmlWebpackPlugin 打包编译HTML的
    • 把打包后的JS/CSS自动导入到页面中
    • 对HTML进行压缩处理
    • ...
  • webpack-dev-server 项目开发的流程:本地开发「边开发、边看效果 开发环境」-> 提测「打包,部署到测试服务器」-> 重新打包,部署到服务器上「生产环境」
    • 基于Node在客户端本地启动一个Web服务,帮助开发者预览开发的作品
    • 第一步:项目打包「打包后的内容没有放在dist目录下,放在了虚拟内存中」
    • 第二步:启动web服务器「从虚拟内存中获取打包的内容,进行实时预览」
    • 第三步:热更新「当代码修改后,会实时进行打包编译,自动刷新浏览器,渲染最新的效果」 => vscode中的LiveServer插件也是做这个事情的
    • 启动的Web服务器,可以作为数据跨域请求的代理服务器,也就是可以实现Proxy跨域代理!!
    • ...

CSS全套处理解决方案

  • 补充

    • css-loader:将CSS文件转换为JavaScript对象(包含对CSS类、样式等的引用和处理)

      1. 处理@importurl()引用

      2. 处理CSS样式:将CSS代码中的样式规则解析为JavaScript对象,并创建可应用于相应元素的样式

      3. 支持CSS模块化:为每个CSS类生成一个唯一的标识符,以避免全局样式冲突,并通过JavaScript对象导出这些标识符,以便在应用程序中使用

      4. 自动添加CSS前缀:对不同浏览器的广泛兼容性

      5. 解析嵌套规则:如&选择器和嵌套选择器,以便正确地应用样式

  • 步骤

image.png

  • mini-css-extract-plugin 抽离CSS样式

www.npmjs.com/package/min…
$ yarn add mini-css-extract-plugin -D

  • 浏览器兼容

    • 兼容IE9+
      package.json OR.browserslistrc
    // https://github.com/browserslist/browserslist
    
    "browserslist": [
    
      "> 1%",
    
      "last 2 versions",
    
      "not dead"
    
    ]
    
    • 考虑CSS3样式的兼容问题

      • postcss-loader & autoprefixer

      • 根据browserslist,自动给CSS3加相关的前缀
        postcss.config.js

    /* 关于POSTCSS-LOADER的配置项 */
    module.exports = {
        plugins: [
            require("autoprefixer")
        ]
    };
    
    • 设置优化项:压缩CSS/JS

    $ yarn add css-minimizer-webpack-plugin terser-webpack-plugin -D

    const TerserPlugin = require('terser-webpack-plugin');
    
    const CssMinimizerWebpackPlugin = require('css-minimizer-webpack-plugin');
    
    module.exports = {
    
        optimization: {
    
            // 设置压缩方式
    
            minimizer: [
    
                new CssMinimizerWebpackPlugin(),
    
                new TerserPlugin()
    
            ]
    
        }
    
    };
    
    • 设置解析器:配置别名
    module.exports = {
    
        resolve: {
    
            alias: {
    
                '@': path.resolve(__dirname, './src')
    
            }
    
        }
    
    };
    
    • 图片的处理

    $ yarn add file-loader url-loader -D

    
    module.exports = {
    
        ...
    
        module: {
    
            rules: [
    
            ...
    
            {
    
                test: /.(png|jpe?g|gif)$/i,
    
                type: 'javascript/auto',
    
                use: [{
    
                    // 把指定大小内的图片BASE64
    
                    loader: 'url-loader',
    
                    options: {
    
                        limit: 200 * 1024,
    
                        esModule: false,
    
                        name: 'images/[name].[hash].[ext]'
    
                    }
    
                }]
    
            }]
    
        },
    
        // 设置打包的最大资源大小
    
        performance: {
    
            maxAssetSize: 100 * 1024 * 1024 * 1024,
    
            maxEntrypointSize: 100 * 1024 * 1024 * 1024
    
        }
    
    };
    

考虑JS的兼容性

  • ES6+语法兼容:把ES6+语法转换为ES5的语法 babel & babel-loader & @babel/preset-env & @babel/core & browserslist
  • ES6+内置API的兼容:上述操作处理不了,需要导入@babel/polyfill「对常见的内置API进行了重写」,不是所有API都重写了,例如:fetch/Reflect等就没有重写!!

image.png

自定义webpack打包规则

webpack.config.js

const path = require('path')
module.exports = {
  /* 
    设置环境模式  
      获取环境变量 process.env.NODE_EVN
      production生产环境:打包后的JS会自动压缩、NODE_EVN="production"
      development开发环境:代码不会压缩、NODE_EVN="development"
    */
  mode: 'production',
  /* 指定入口「相对地址」 */
  entry: './src/index.js',
  /* 指定出口 */
  output: {
    // 打包后文件的名字
    //  [hash]/[hash:8]:为打包后的文件创建哈希名
    //   + 代码一但被修改,生成的文件名中的哈希值也会变化
    //   + 有助于强缓存的设置
    // hash:8 保留八位hash值
    filename: 'main.[hash:8].js',
    // 设置打包的路径「绝对路径」
    // path是Node内置的路径处理模块
    // _dirname:获取当前文件所在目录的绝对路径
    // path.resolve:在某一个绝对路径上基于后面的相对路径,获取一个全新的绝对路径地址
    path: path.resolve(__dirname, './dist'),
  },
}

proxy代理

  • 除是前后端不分离的项目都要跨域

image.png

image.png