webpack配置

/**
 * 开发环境的配置: 能让代码运行即可
 *    整体流程: 源代码 --> webpack(+自动化) --> bundle(输出文件)
 */

const { resolve } = require('path');

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

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

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

const WorkboxWebpackPlugin = require('workbox-webpack-plugin');

const webpack = require('webpack');

const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin');

// process.env.NODE_ENV = 'development';

module.exports = {
  entry: ['./src/index.js', './src/index.html'],
  output: {
    filename: 'js/build.js',
    path: resolve(__dirname, 'build'),
  },

  // loader配置
  module: {
    rules: [
      {
        // 匹配的文件
        test: /\.css$/,
        // 使用的loader
        // use数组执行顺序从后往前!!!
        use: [
          // 创建style标签,将js中的样式资源插入进行,添加到head中生效
          'style-loader',
          // 将css文件变成commonjs模块加载到js中,里面的内容是字符串
          'css-loader',
        ],
      },

      {
        test: /\.less$/,
        use: [
          // 'style-loader',
          MiniCssExtractPlugin.loader,
          'css-loader',

          // css兼容性处理: postcss --> 安装postcss-loader 和 postcss-preset-env
          // postcss-preset-env帮助postcss找到package.json中browserslist里面的配置,通过配置加载指定的css兼容性样式
          // browserslist:{
          //   // 开发环境 --> 设置node环境变量: process.env.NODE_ENV = "development" 可以看development
          //   "development":[
          //     "last 1 chrome version",
          //     "last 1 firefox version",
          //     "last 1 safari version"
          //   ],
          //   // 生产环境: 默认postcss-preset-env是看production
          //   "production": [
          //     ">0.2%",
          //     "not dead",
          //     "not op_mini all"
          //   ]
          // }
          {
            loader: 'postcss-loader',
            options: {
              ident: 'postcss',
              plugins: () => [require('postcss-preset-env')()],
            },
          },
          // 将less文件编译成css文件  需要下载 less 和 less-loader两个包
          'less-loader',
        ],
      },

      {
        test: /(\.sass)|(\.scss)$/,
        use: [
          'style-loader',
          'css-loader',
          // 将sass文件编译成css文件  需要下载 sass 和 sass-loader两个包
          'sass-loader',
        ],
      },

      // 处理图片资源
      // 默认处理不了html中img标签的图片!!!
      {
        test: /\.(jpg|png|gif)$/,
        // 下载url-loader file-loader (url-loader依赖与file-loader)
        loader: 'url-loader',
        options: {
          // 图片大小小于8Kb就会被base64处理
          // 优点: 减少请求数量(减轻服务器压力)
          // 缺点:图片体积会更大(文件请求速度更慢)
          limit: 8 * 1024,
          // [hash:10]表示取图片的hash值前10位
          // [ext]表示取文件原来扩展名
          name: '[hash:10].[ext]',

          // 关闭url-loader的es6模块化,使用commonjs模块化
          ESModule: false,
          outputPath: 'imgs',
        },
      },

      {
        test: /\.html$/,
        // 处理html文件的img图片(负责引入img,从而能被url-loader处理)
        loader: 'html-loader',
      },

      // 打包其他资源 (直接生成不需要进行其他操作的文件)
      {
        exclude: /\.(css|js|less|html|jpg|png|gif)$/,
        loader: 'file-loader',
        options: {
          name: '[hash:10].[ext]',
          outputPath: 'media',
        },
      },

      /**
       * 语法检查: eslint-loader  eslint
          注意: 只需要检查源代码,第三方的库不需要检查
          设置检查规则:
            在package.json 中 eslintConfig中设置
            使用airbnb语法规则  --> 安装 eslint-config-airbnb-base eslint-plugin-import  eslint
      */

      /**
       * 当一个文件要被多个loader处理时,一定要指定loader执行的先后顺序
       *   先执行eslint,再执行babel
       *   enforce:'pre'
       */
      // {
      //   test: /\.js$/,
      //   exclude: /node_modules/,
      //   loader: 'eslint-loader',
      //   enforce: 'pre',
      //   options: {
      //     fix: true,
      //   },
      // },

      // js兼容性处理
      // 安装 babel-loader  @babel/core  @babel/preset-env
      /**
       * 1. 基本js兼容性处理 --> @babel/preset-env
       *  problem: 只能转化基本语法,如promise等高级语法不能转换
       * 2. 全部js兼容性处理 --> @babel/polyfill (不需要写配置,只需要在入口文件的js文件中引入)
       *  problem: 只需要解决部分兼容性问题,但是将所有兼容性代码全部引入,体积太大了
       * 3. 按需加载js兼容性  --> core-js(需要配合@babel/preset-env使用)
       *
       */
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: {
          // 预设: 指示babel做怎么样的兼容性处理
          presets: [
            [
              '@babel/preset-env',
              {
                useBuiltIns: 'usage',
                corejs: { version: 3 },
                targets: {
                  chrome: '60',
                  firefox: '60',
                  ie: '9',
                  safari: '10',
                  edge: '17',
                },
              },
            ],
          ],
        },
      },
    ],
  },

  // optimization: {
  //   splitChunks: {
  //     chunks: 'all',
  //   },
  // },

  // plugins配置
  // 使用插件,要先下载,然后引入,最后使用!!
  plugins: [
    // html-webpack-plugin
    // 默认会创建一个空的html,自动引入打包输出的所有资源(JS/CSS)
    new HtmlWebpackPlugin({
      template: './src/index.html',
      // minify: {
      //   collapseWhitespace: true,
      //   removeComments: true,
      // },
    }),
    new MiniCssExtractPlugin({
      filename: 'css/index.css',
    }),
    new OptimizeCssAssetsWebpackPlugin(),
    new WorkboxWebpackPlugin.GenerateSW({
      clientsClaim: true,
      skipWaiting: true,
    }),

    // 告诉webpack这些库不参与打包,同时使用时的名称也得改变
    new webpack.DllReferencePlugin({
      manifest: resolve(__dirname, 'dll/manifest.json'),
    }),

    // new AddAssetHtmlWebpackPlugin({
    //   filepath: resolve(__dirname, 'dll/jquery.js'),
    // }),
  ],

  // development特点: 能让代码本地调试运行的环境
  // production特点: 能让代码优化上线运行的环境
  mode: 'development',
  // mode: 'production',

  // 开发服务器devServer: 用来自动化(自动编译、自动打开浏览器、自动刷新浏览器)
  // 特点: 只会在内存中编译打包,不会有任何输出
  // 启动devServer指令: npx webpack-dev-server
  // 本地运行的包使用npx, 由于webpack是-g全局安装,所以不需要使用npx
  devServer: {
    contentBase: resolve(__dirname, 'build'),
    watchContentBase: true,
    // 如果出错了,不要全屏提示
    overlay: false,
    // 除了一些基本启动信息外,其他内容不要显示
    quiet: true,
    // 不要显示启动服务器日志信息
    clientLoglevel: 'none',
    compress: true,
    open: true,
    hot: true,
    port: 3000,
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        pathRewrite: {
          // 发送请求时重写路径,将 /api/xxx --> /xxx (去掉/api)
          '^/api': '',
        },
      },
    },
  },

  devtool: 'source-map',

  resolve: {
    // 配置解析模块路径别名:简写路径
    alias: {
      $: resolve(__dirname, 'src'),
    },
    // 配置省略文件路径的后缀名
    extensions: ['.json', '.js', '.jsx'],
    // 告诉webpack解析模块是去找哪个目录
    modules: [resolve(__dirname, 'node_modules'), 'node_modules'],
  },
};
// webpack 优化配置
/**
 * 1. 开发环境性能优化
 *   * 优化打包构建速度(HMR --> hot module replacement  热模块替换)
 *      作用: 一个模块发生变化,只能重新打包这一个模块(而不是重新打包所有模块)
 *
 *      样式文件:可以使用HMR功能 --> 因为style-loader内部实现了 (开发环境使用style-loader)
 *      js文件: 默认不能使用HMR --> 需要修改js代码,添加支持HMR功能的代码
 *          注意: HMR功能对js的处理,只能处理非入口js文件
 *      html文件: 默认不能使用HMR功能,同时会导致html文件不能热更新了(HMTML文件只有一个不需要做HMR功能)
 *          解决: 修改entry入口,将html文件引入
 *
 *   * 优化代码调试(source-map)
 *      source-map: 提供源代码到构建后代码映射的技术(如果构建后代码出错,通过映射可以追踪源代码错误)
 *      devtool: 'source-map'
 *
 *      source-map: 外部
 *          能提示 错误代码准确信息 和 源代码的错误位置
 *      inline-source-map: 内联(只生成一个内联source-map)
 *          能提示 错误代码准确信息 和 源代码的错误位置
 *      hidden-source-map: 外部
 *          能提示 错误代码错误原因,但是没有错误位置,不能追踪到源代码的错误位置,只能提示到构建后代码的错误位置
 *      eval-source-map:  内联(每一个文件都生成对应的source-map,都在eval)
 *          能提示 错误代码准确信息 和 源代码的错误位置
 *      nosources-source-map: 外部
 *          能提示错误代码准确信息,但是没有任何源代码细信息
 *      cheap-source-map: 外部
 *          能提示 错误代码准确信息 和 源代码的错误位置,但是只能精确到行
 *      cheap-module-source-map: 外部
 *          能提示 错误代码准确信息 和 源代码的错误位置
 *      内联和外部的区别:1. 外部生成了文件,内联没有;2. 内联构建速度更快
 *
 * 2. 生产环境性能优化(生产环境不能用HMR功能)
 *   * 优化打包构建速度
 *   * 优化代码运行的性能
 */

/**
 * oneOf  以下loader只会匹配一个
 * 注意: 不能有两个配置处理统一类型文件
 */

/**
 * 缓存:
 * 1.babel缓存
 *   cacheDirectory: true   开启babel缓存(第二次构建时,会读取之前的缓存)
 *
 *   目的:让第二次打包构建速度更快
 * 2.资源缓存
 *   修改文件名(给文件添加hash值,每次webpack构建时会生成一个唯一hash值)
 *   问题:因为js和css同时使用一个hash值,如果只修改js(css文件不变),重新打包,会导致所有缓存失效(css缓存也失效了)
 *
 *   使用chunkhash:根据chunk生成的hash值(如果打包来源于同一个chunk,那么hash值一样)
 *     问题:js和css的hash值还是一样的
 *       因为css是在js中被引入的,所以属于同一个chunk
 *   使用contenthash:根据文件的内容生成hash值。不同文件hash值一定不一样
 *
 *   目的:让代码上线运行缓存更好使用
 */

/**
 * tree shaking (树摇)
 * 前提:
 * 1. 必须使用ES6模块化
 * 2. 开启production环境
 *
 * 作用: 去除无用的代码,减少代码体积
 *
 *
 * 在package.json中配置 "sideEffects":false  所有代码都没有副作用(都可以进行tree shaking)
 *  问题: 可能会把css / @babel/polyfill 等(有副作用)文件去除
 *  方法:"sideEffects";["*.css","*.less"] (标记这些文件为副作用文件,不进行tree shaking)
 */

/**
 * code split (代码分割)
 * 分为多个文件可以并行加载,提高速度,还可以按需加载
 *
 * 方式一:
 * 多入口:
 * entry:{
 *   index: './src/index.js',
 *   test: './src/test.js'
 * }
 *
 * output: {
 *   filename: 'js/[name].[contenthash:10].js'
 * }
 *
 *
 * 方式二:
 * 1. 可以将node_modules中代码单独打包一个chunk最终输出
 * 2. 自动分析多入口chunk中有没有公共的文件,如果有会打包程单独一个chunk
 * optimization: {
 *   splitChunks: {
 *     chunks: all
 *   }
 * }
 *
 *
 * 方式三:
 * 通过js代码,让某个文件被单独打包成一个chunk
 * import 动态导入语法:能将某个文件单独打包
 * import('./test').then().catch()
 *
 */

/**
 * 懒加载(lazy load)和预加载(prefetch)
 * 懒加载:当文件需要使用时才加载;
 * 预加载:会在使用之前,提前加载js文件(兼容性比较差,慎用!)
 *   正常加载可以认为是并行加载(同一时间加载多个文件),而预加载是指等其他资源加载完毕等浏览器空闲了再加载
 */

/**
 * PWA:渐进式网络开发应用程序(离线可以访问)
 * (serviceWork 和 cache) --> 兼容性差
 * workbox --> workbox-webpack-plugin
 *
 * new WorkboxWebpackPlugin
 */

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值