webpack 初识

70 阅读4分钟

为什么使用webpack?

  随着前端的发展,各种工程化的出现,ES6、TS、及各种css预处理器、模块化、各种框架等的出现,也就是为了应对各种应用的开发,流程越来越复杂,不同规范的出现保证效率及安全性,及各种浏览器的适配,开发过程的各种问题webpack也就出现了。

先说一下webpack打包的依赖,也就是说打包时需要的入口及出口问题,入口的话默认回去找我们src文件下的index.js文件,也就是打包的入口,在基于模块化思想下,index.js下各种依赖不同模块,例如home.js模块下也可能依赖各种图片啊、css文件及api文件等,webpack        也就是通过index文件各种模块的依赖来进行的打包,然后通过不同的loader进行处理不同的文件。这也就是webpack的依赖关系,说的不对的地方多多指教。

再说一下webpack的配置文件,放到开发文件的一级目录中和package.json同级,默认的名字叫webpack.config.js文件,也可以通过package.json文件中脚本运行来起一个不同的名字,用来在多人协作开发中进行各自的配置。可以在pakeage.josn中运行脚本时进行书写            webpack --config test.webpack.config.js,这样的话我们在test.webpack.config.js文件中修改webpack的配置就可以让我们在自己开发中配置自己需要的东西。入口文件及出口文件的配置:

const path = require('path');
module.exports = {
  entry: './src/index.js', // 入口文件是不需要绝对路径的  不强制
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'build') // 但是出口文件的路径时强制需要使用绝对路径的
  },
}

 

loader的使用:

  webpack中loader的使用,因为webpack只能转化js文件,其他模块文件的引入需要不同的loader进行处理,这也就是如果我们引入了css文件的话,没有用到loader的话在打包的过程中会报错,提示我们需要引入css-loader。先说一下css文件引入需要的loader有哪些,

const path = require('path');
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'build')
  },
  module: {
    rules: [
      // {
      //   test: /.css$/, //一般就是一个正则表达式,用来匹配我们需要处理的文件类型
      //   use: [
      //     {
      //       loader: 'css-loader'
      //     }
      //   ]
      // },
      // {
      //   test: /.css$/,
      //   loader: 'css-loader'
      // },
      {
        test: /.css$/,
        use: ['style-loader', 'css-loader']
      },
// 上边是代表的引入loader的三种写法,可以根据我们个人习惯进行编写
    ]
  }
}

     除了这些常规的loader,假如我们需要进行兼容各种浏览器,添加游览器前缀,或者我们需要兼容什么浏览器,那些浏览器占比高这些操作都可以通过webpack进行优化,我们可以通过browerslist来进行配置我们需要兼容那些浏览器,可以通过配置.browserslistrc来配置浏览器兼容的规则。

>1%      //浏览器占比大于1%的
last 2 version   // 最后两个版本
not dead   // 没有停止跟新的    一年内没有更新就默认认为停止了更新

    browserslist这个插件不能单独使用,他只能计算出需要适配的浏览器有哪些,我们需要添加浏览器前缀的话需要配合autoprefixer或者babel或postcss等插件使用,也可以安装browserslist-cli用npx browserslist进行操作。我们结合postcss-loader和autoprefixer这进行配置一下。

const path = require('path');
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: path.resolve(__dirname, 'build')
  },
  module: {
    rules: [
      {
        test: /.css$/,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              postcssOptions: {
                plugins: [
                  require('autoprefixer')
                ]
              }
            }
          }
        ] // 也是需要postcss-loader处理完成后交给css-loader处理然后交给style-loader 
      }
    ]
  }
}

 常用plugins的使用:

plugins: [
    new CleanWebpackPlugin(), // 打包前清除原有打包好的文件
    new HtmlWebpackPlugin({   // 打包生成一个html入口文件,可以根据模板动态生成这个入口文件   详细配置可以去查官网  只列举了常用的
      title: 'webpack_test', // 网页title
      template: './public/index.html' // 模板文件地址
    }),
    new DefinePlugin({ // 定义全局变量
      BASE_URL: '"./"'
    }),
    // new CopyWebpackPlugin({
    //   patterns: [
    //     {
    //       from: path.resolve(__dirname, 'public'),
    //       globOptions: {
    //         // 排除  可以排除掉多项
    //         ignore: ['**/index.html']
    //       }
    //     }
    //   ]
    // })
  ],

babel是使用:babel是用来将一些JSX、vue、es6等语法进行转换成浏览器可以识别的js语法。和post-css用法差不多,就是将一些浏览器不识别的代码在打包过程中转换成浏览器可以识别的代码。识别也是依赖一些插件还有就是browserslist插件中我们配置的需要兼容的那 些浏览器。

{
        test: /.m?js$/,
     exclude: /node-modules/,
        // use: ['babel-loader'],
        use: [
          // 这是配置在loader中的写法
          {
            loader: 'babel-loader',
            options: {
              presets: [
                [
                  '@babel/preset-env',
                  {
                    useBuiltIns: "entry",
                    targets: { chrome: "91" }
                    // caller.target 等于 webpack 配置的 target 选项
                    // targets: api.caller(caller => caller && caller.target === "node")
                    //   ? { node: "current" }
                    //   : { chrome: "58", ie: "11" }
                  }
                ]
              ]
            }
          }
        ]
      },

还有就是放到babel.config.js文件中,和我们browerslistrc文件一样,导出一个对象。

module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        useBuiltIns: "entry",
        targets: { chrome: "91" }
        // caller.target 等于 webpack 配置的 target 选项
        // targets: api.caller(caller => caller && caller.target === "node")
        //   ? { node: "current" }
        //   : { chrome: "58", ie: "11" }
      }
    ]
  ]
}

 preset-env一般的语法是可以进行转换的,如果一些generator、promise等的语法就需要用到polyfill这个插件,如果是webpack4的话是webpack自己给我们配置好的,但是因为这个东西比较的大,加上这个东西以后可能会造成打包体积比较大,所以在webpack5中交给我们自己去配置。我这也是直接在babel.config.js文件中进行了配置。

module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        /**
         * useBuiltIns有三个值
         * false 就是不会引入polyfill
         *  entry 的话就是根据我们browserslistrc配置的浏览器适配  这个是根据浏览器不管你有没有写过需要适配的代码都会给你加载进去
         * usage 依据我们borwserslistrc中配置产生的浏览器 然后根据我们写的代码去适配浏览器  
         * 需要加的插件时core-js和regenerator-runtime这两个插件  因为在下载polyfill的时候给我们了一个警告,打开官网后给我们的提示时这两个插件包括了原有的功能 core-js专门做语法功能  regenerator-runtime是用来处理symbol、generator、async等的
         * */
        useBuiltIns: "entry",

      corejs: 3, // 默认是版本2   我们下载没有特定的话是最新的  所以需要手动改一下

        targets: { chrome: "91" }
        // caller.target 等于 webpack 配置的 target 选项
        // targets: api.caller(caller => caller && caller.target === "node")
        //   ? { node: "current" }
        //   : { chrome: "58", ie: "11" }
      }
    ]
  ]
}