美文网首页
webpack基础使用(四)

webpack基础使用(四)

作者: JerrySi | 来源:发表于2022-01-09 20:56 被阅读0次
十四、ts
  1. ts-loader帮助我们处理ts文件, 编译的时候就可以处理语法错误。
// 安装
yarn add ts-loader --dev

// webpack.config.js
entry: './src/index.js' => entry: './src/index.ts'

// webpack.config.js
      {
        test: /\.ts$/,
        use: ['ts-loader']
      }
  1. preset-typescript,支持polyfill填充,进行语法转化。但是不能再编译时候就判断语法错误。
// 安装
yarn add @babel/preset-typescript --dev

// webpack.config.js
      {
        test: /\.ts$/,
        exclude: /node_modules/,
        // use: ['ts-loader']
        use: ['babel-loader']
      }

// babel.config.js
module.exports = {
    presets: [
      [
        '@babel/preset-env',
        {
          useBuiltIns: 'usage',
          // 默认版本2
          corejs: 3
        }
      ],
      // 识别ts文件
      [ '@babel/preset-typescript' ]
    ]
  }
  1. 结合使用
// package.json
"scripts": {
    // --noEmit 不生成文件,只是校验
    "build": "tsc --noEmit &&  webpack",
    "serve": "webpack serve"
  }
十四、环境
  1. paths.js, 不能叫path, 会内部重名.
// 整体处理webpack config里面的路径
// 这里就不使用相对路径
const path = require('path')

const appDir = process.cwd()

const resolveApp = (relativePath) => {
  return path.resolve(appDir, relativePath)
}

module.exports = resolveApp
  1. 公共配置部分webpack.common.js

const resolveApp = require('./paths')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { DefinePlugin } = require('webpack')
const { merge } = require('webpack-merge')

// 导入其它的配置
const prodConfig = require('./webpack.prod')
const devConfig = require('./webpack.dev')
const VueLoaderPlugin = require('vue-loader/lib/plugin')

// 定义对象保存 base 配置信息
const commonConfig = {
    // 反而没有报错( 相对路径, 相对于content配置路径) 
    // 这里content没有配置,就找的是package.json里面的webpack config的目录相对路径
    entry: './src/index.js',
    devtool: 'source-map',
    resolve: {
      // 添加新的扩展名
      extensions: [".js", ".json", '.ts', '.jsx', '.vue'], 
      // 添加别名
      // import Home from './components/Home' 
      // =>
      // import Home from '@/components/Home'
      alias: {
        // 使用相对路径
        '@': resolveApp('./src')
        //'@': path.resolve(__dirname, './src')
      }
    },
    output: { 
      filename: 'js/main.js',
      // 输出到哪儿
      // 使用相对路径
      path: resolveApp('./dist'),
      // path: path.join(__dirname, 'dist'),
      // 默认空字符串, 浏览量会帮我们添加/
      // publicPath: ''
      // 自己添加/, 但是这样本地路径会找不到
      // publicPath: '/'
      // 相对路径, 本地可以访问,但是webpack serve会找不到 
      // publicPath: './'
      // publicPath: '/lg'
      // assetModuleFilename: 'img/[name].[hash:4][ext]'
    }, 
    module: {
      rules: [
        {
          test: /\.css$/,
          use: ['style-loader', {
            loader: 'css-loader',
            options: {
              // 代表向前找一个loader处理
              importLoaders: 1,
              esModule: false
            }
          }, 'postcss-loader']
        },
        {
          test: /\.less$/,
          use: ['style-loader', {
            loader: 'css-loader',
            options: {
              // 代表向前找一个loader处理
              importLoaders: 1,
              esModule: false
            }
          }, 'postcss-loader', 'less-loader']
        },
        // 全部转成base64
        // {
        //   test:/\.(png|svg|gif|jpe?g)$/,
        //   type: 'asset/inline'
        // }
        // 使用
        {
          test:/\.(png|svg|gif|jpe?g)$/,
          type: 'asset',
          generator: {
            filename: 'img/[name].[hash:4][ext]'
          },
          parser: {
            dataUrlCondition: {
              maxSize: 20 * 1024
            }
          }
        },
        {
          test: /\.(ttf|woff2?)$/,
          type: 'asset/resource',
          generator: {
            filename: 'font/[name].[hash:3][ext]'
          }
        },
        {
          // js或者jsx
          test: /\.jsx?$/,
          // 防止node_modules中的库也使用了babel,导致干扰
          exclude: /node_modules/,
          use: [ 'babel-loader' ]
        },
        {
          test: /\.vue$/,
          exclude: /node_modules/,
          use: ['vue-loader']
        },
        {
          test: /\.ts$/,
          exclude: /node_modules/,
          // use: ['ts-loader']
          use: ['babel-loader']
        }
      ]
    },
    plugins: [
      new HtmlWebpackPlugin({
        title: 'jerry-webpack-plugin',
        template: './public/index.html'
      }),
      // 定义常量
      new DefinePlugin({
        // 这里要添加双引号,DefinePlugin会把数据原封不动返回
        BASE_URL: '"./"'
      }),
      // 针对vue-loader > 15的版本,需要手动设置插件
      new VueLoaderPlugin()
    ]
  }

module.exports = (env) => {
    const isProduction = env.production

    // 设置线程环境, 让config中也可以判断环境
    process.env.NODE_ENV = isProduction ? 'production' : 'development'
  
    // 依据当前的打包模式来合并配置
    const config = isProduction ? prodConfig : devConfig
  
    const mergeConfig = merge(commonConfig, config)
  
    return mergeConfig
  }
  1. 正式环境webpack.prod.js
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')

module.exports = {
  mode: 'production', 
  plugins: [
    new CleanWebpackPlugin(),
    new CopyWebpackPlugin({
      patterns: [
        {
          // 省略了to,to默认output.path的文件夹
          from: 'public',
          globOptions: {
            // index.html上面已经操作过了,需要排除。
            // 默认从项目根找, **代表从当前目录找
            ignore: ['**/index.html']
          }
        }
      ]
    })
  ]
}
  1. 测试环境webpack.dev.js
const resolveApp = require('./paths')
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin')

module.exports = {
  mode: 'development',
  devtool: 'cheap-module-source-map',
  // 开发阶段屏蔽 .browserslistrc
  target: 'web',
  // 开启HMR
  devServer: {
    // 只热加载变化的部分
    hot: 'only',
    // 开启压缩
    compress: true,
    // 处理直接向后端请求,导致404的问题
    historyApiFallback: true,
    proxy: {
      // /info/users
      // http://localhost:4000/info/users
      // https://api.github.com/info/users
      '/info': {
        target: 'https://api.github.com',
        // 重写
        pathRewrite: { "^/info": "" },
        // 修改host
        changeOrigin: true
      }
    },
    static: {
      // 代表生成的文件在哪儿, 需要output里面publicPath和这里一致
    //   publicPath: '/lg',
      // 我们打包之后的资源如果说依赖其它的资源,此时就告知去哪找。
      // 强烈建议使用绝对路径
      directory: resolveApp('./public'),
      // 监听directory
      watch: true
    }
  },
  plugins: [
    // 负责让把具体要使用的插件和webpack结合起来
    new ReactRefreshWebpackPlugin()
  ]
}
  1. 根据环境配置 babel.config.js
const presets = [
  [
    '@babel/preset-env',
    {
      // false: 不对当前的JS处理做 polyfill 的填充
      // usage: 依据用户源代码当中所使用到的新语法进行填充
      // entry: 依据我们当前筛选出来的浏览器决定填充什么
      // 使用entry,需要在使用的地方导入头文件
      // import "core-js/stable";
      // import "regenerator-runtime/runtime"
      useBuiltIns: 'usage',
      // 默认版本2
      corejs: 3
    }
  ],
  // 识别jsx文件
  [ '@babel/preset-react' ],

  // 识别ts文件
  [ '@babel/preset-typescript' ]
]

const plugins = []
// 依据当前的打包模式来决定plugins 的值 
const isProduction = process.env.NODE_ENV === 'production'
if (!isProduction) {
  plugins.push(['react-refresh/babel'])
}

module.exports = {
    presets,
    plugins
  }

  1. package.json
"scripts": {
    "build: "tsc --noEmit &&  webpack --config ./config/webpack.common.js --env production",
    "serve": "webpack serve --config ./config/webpack.common.js --env development"
  }
十五、分模块打包

可以方便加载的时候,只是加载当前需要的模块,而不是一起都加入到项目中。

  1. 多入口
const commonConfig = {
    entry: {
      main1: './src/main1.js',
      main2: './src/main2.js'
    },
    output: { 
      // filename: 'js/main.js',
      // [name]占位
      filename: 'js/[name].build.js'
    }
  }
  1. 依赖方式
const commonConfig = {
    entry: {
      main1: { import: './src/main1.js', dependOn: 'lodash' },
      main2: { import: './src/main2.js', dependOn: 'lodash' },
      lodash: 'lodash'
      // 同时依赖多个
      // main1: { import: './src/main1.js', dependOn: 'shared' },
      // main2: { import: './src/main2.js', dependOn: 'shared' },
      // shared: ['lodash', 'jquery']
    },
    output: { 
      // filename: 'js/main.js',
      // [name]占位
      filename: 'js/[name].build.js'
    }
  }
  1. chunk模式
// webpack.common.js
// webpack 5 自带
const TerserPlugin = require("terser-webpack-plugin")
const commonConfig = {
    entry: {
      index: './src/index.js'
    },
    optimization: {
      minimizer: [
        new TerserPlugin({
          // 默认会生成一个注释文件, 这里去除
          extractComments: false,
        }),
      ],
      splitChunks: {
        // all代表同步和异步加载都分模块
        chunks: 'all'
      }
    }
}

// 会生成767.build.js,767是chunkId
  1. splitChunks, 静态拆分
splitChunks: {
        // all代表同步和异步加载都分模块
        // initial代表同步
        chunks: 'initial',  // async initial all
        // 体积大于20KB的进行拆分, 而且拆分后最小20KB
        // 一般minSize和maxSize 的值一样
        minSize: 20000, // 20KB
        maxSize: 20000, // 20KB
        // minSize 和 maxSize优先级 高于 minChunks。
        // 如果要一起使用,就这样设置
        // minChunks代表最少import 引用了一次
        minChunks: 1,
        // 处理好了, 先放缓存, 后面处理好了, 再看是否合并
        cacheGroups: {
          // syVendors 和 default 名字随便定义
          syVendors: {
            // node_modules文件夹里面,代表三方库
            // \/代表不同系统里面的路径符号
            test: /[\\/]node_modules[\\/]/,
            // filename 可以使用占位符
            filename: 'js/[id]_vendor.js',
            // 优先级, 默认-10。 数字越大优先级越高
            priority: -10,
          },
          default: {
            // import 2次的才拆分
            minChunks: 2,
            filename: 'js/syy_[id].js',
            priority: -20,
          }
        }
      }
  1. 动态导入
    动态导入的会进行自动拆分模块
// 动态导入
// 魔法注释, 会把title作为chunk的名字
import(/*webpackChunkName: "title"*/'./title')

// webpack.common.js
output: { 
      // 设置chunk文件输出名字
      chunkFilename: 'js/chunk_[name].js'
    }, 
    optimization: {
      // natural 按自然数进行编号排序,如果某个文件当前次不再被依赖那么重新打包时序号都会变
      // named 建议开发环境使用,名字长会影响性能
      // deterministic 生产环境使用
      chunkIds: 'deterministic',
      minimizer: [
        new TerserPlugin({
          // 默认会生成一个注释文件, 这里去除
          extractComments: false,
        }),
      ]
    }
  1. runtime chunk
    可以将加载模块的信息抽取出来, 方便做缓存。
    optimization: {
      // 将加载模块的信息抽取出来,生成一个新的runtime文件
      // runtimeChunk: true,
      // 同样的导入信息, 只有一个runtime
      runtimeChunk: 'single'

      /*其他*/
   }

bundle: 直接部署,入口文件
vendor:三方的库,node_modules下面
chunk: 依赖代码块
runtime:连接信息,方便缓存

相关文章

  • webpack基础使用(四)

    十四、ts ts-loader帮助我们处理ts文件, 编译的时候就可以处理语法错误。 preset-typescr...

  • webpack进阶——缓存与独立打包

    系列:webpack入门——了解及使用webpack基础——常用配置解析 先来看看最基础的webpack配置: 在...

  • webpack 基础使用

    module.exports = {mode:"development", //定义当前开发环境(默认 prod...

  • webpack基础使用

    上一篇《什么是构建?webpack打包思想》webpack是在node环境里跑的,所以先搭建构建环境。node的安...

  • webpack基础使用

    安装 常见的project下有src目录和dist目录,src表示源,常用来放编译前的原始代码,dist表示分布,...

  • Webpack基础使用

    一、 1.1初始化项目 npm init -y 1.2安装Webpack npm install webpack ...

  • Webpack 4 学习03(配置入口和出口的进阶使用)

    前提:知道webpack4的基础配置以及如何使用配置文件进行打包第一讲 Webpack 4 学习01(基础配置) ...

  • html-webpack-plugin插件使用

    本篇在webpack-dev-server的使用的基础上 html-webpack-plugin html-web...

  • webpack的基础使用

    如果是直接用vue-cli脚手架搭建的vue项目, webpack会先提前配置好 最原始的关于webpack使用的...

  • webpack-基础使用

    网页静态资源 1.在网页中会引用哪些常见的静态资源? JS .js .jsx .coffee .ts(Typ...

网友评论

      本文标题:webpack基础使用(四)

      本文链接:https://www.haomeiwen.com/subject/ltoycrtx.html