webpack

600 阅读4分钟

入口/出口

npx 打包,使用 npm init -y 进行初始化(也可以使用 yarn)。要使用 webpack,那么必然需要安装 webpack、

webpack-cli:
1.
    const path = require('path');
    module.exports = {
      // 入口文件路径
      entry: './path/to/my/entry/file.js',
      // 出口
      output: {
        // 打包后引入js文件的前缀
        publicPath: 'http://cdn.xxx.com'
        // 打包文件输出的路径
        path: path.resolve(__dirname, 'dist'),
        // 打包后文件名字
        filename: 'main.js',
      }
    };
    
2.
     module.exports = {
      // 入口文件路径
      entry: {
          // 打包后的文件名字
          text: './path/to/my/entry/file.js'
      },
      // 出口
      output: {
        // 打包文件输出的路径
        path: path.resolve(__dirname, 'dist'),
      },
    };

3.
     module.exports = {
      // 入口文件路径
      entry: {
          // 打包后的文件名字(多个文件)
          main: './path/to/my/entry/file.js'
          text: './path/to/my/entry/file.js'
      },
      // 出口
      output: {
        // 打包文件输出的路径
        path: path.resolve(__dirname, 'dist'),
        filename:'[name].js'
      },
    };

别名

创建 import 或 require 的别名,来确保模块引入变得更简单。例如,一些位于 src/ 文件夹下的常用模块

const path = require('path');
module.exports = {
  //...
  resolve: {
    alias: {
        Templates$: path.resolve(__dirname, 'src/templates/'), // 精准匹配
        Templates:  path.resolve(__dirname, 'src/templates/'), // 普通匹配
    },
  },
};

处理图标

file-loader:打包图标,字体文件
module.exports = {
    ...
     module: {
         rules: [
           { 
               // 处理字体文件 
               test: /.(eot|svg|ttf|woff)/, 
               use: 'flie-loader' 
           }
         ]
     }
}

处理图片

// file-loader:打包图片,单独文件
// url-loader:打包图片,单独文件,base64格式,可配置:
// base64格式:不生成图片文件,图片过大,打包文件大,页面加载时间长,未加载完图片为空白

// file-loader:打包图片,单独文件
 module.exports = {
     module: {
         ... 
         rules: [
           {
               // 打包图片:当文件后缀为jpg|pan|gif时,使用flie-loader插件打包
               test: /.(jpg|png|gif)$/,
               use: {
                   loader: 'file-loader',
                   options: {
                       // 打包生成的文件,为原来的文件名/格式
                       // 添加哈希值:[name]_[hash].[ext]
                       name: '[name].[ext]' 
                       // 输出文件路径 图片打包到images文件下
                       outputPath:'/images/'
                   }
               }
           },
         ]
     }
};

// url-loader:
    // 打包图片,单独文件,base64格式,可配置, 
    // 优点:少了jpg文件,减少图片的HTTP请求,
    // 缺点:js文件过大,页面加载时间长,加载中空白
    // 优化:图片小于xx的时候:进行打包,大于时生产图片文件,发送请求,js加载时间短
    
 module.exports = {// 
     module: {
         ...
         rules: [
           {
               // 打包图片:当文件后缀为jpg|pan|gif时,使用flie-loader插件打包
               test: /.(jpg|png|gif)$/,
               // use: 'file-loader'
               use: {
                   loader: 'url-loader', 
                   options: {
                       // 打包生成的文件,为原来的文件名/格式
                       // 添加哈希值:[name]_[hash].[ext]
                       name: '[name].[ext]' 
                       // 输出文件路径 图片打包到images文件下
                       outputPath:'/images/'
                       // 设置图片大小(字节)2048 = 2K,
                       // 超过这个大小,生成图片文件
                       limit:2048
                   }
               }
           },
         ]
     }
};

样式处理

// style-loader:生成html中的style标签样式
// css-loader: 处理样式引用关系,css模块化,需配置
// postcss-loader: 处理css3样式,添加前缀兼容代码,需配置
// scss-loader:处理scss样式

module.exports = {
    ...
     module: {
         rules: [
           {
               // 处理.xxx结尾的文件
               test: /.scss$/
               use:[
                   'style-loader',
                   // 没有模块化,可配置
                   'css-loader',
                   'postcss-loader', // 需要配置
                   'scss-loader'
               ]
           }
         ]
     }
}

// css-loader模块化配置: 
// 页面引入css文件: import style from './index.css' 
// index.css 中的样式保存在style这个变量中 
// 添加类名:div.calssNmae = style.item 
// 配置: 
    use:[
       'style-loader',// 
        {
            loader:'css-loader',
            options: {
                modules: true
            }
        },
       'postcss-loader',
       'scss-loader'
    ]
 // 配置postcss-loader
 // npm install atuoprefixer -D
 // package.json 中添加 
     "browserslist":[
         "> 1%" // 大于市场份额的1%浏览器// 
         "last 2versions" // 兼容浏览器的上两个版本
     ]
 // 创建postcss.config.js文件
 module.export = {
     plugins: {
         require('autoPrefixer)
     }
 }

SourceMap

// SourceMap 的主要作用是为了方便调试
// 映射转换过后的代码和源代码之间的关系
// cheap:只记录业务代码,不急了,第三方模块代码(node。。),需记录第三方模块加上module:cheap-module-// source-map
// eval: 速度快
// cheap-module-source-map:打包生成单独的文件,记录行数,列数
// inline-cheap-module-source-map:打包生成的文件存放在出口文件中,记录行数,列数
// inline-module-source-map: 打包生成的文件存放在出口文件中,记录行数
module.exports = {
    ...
    // 启用
    devtool: 'cheap-module-source-map'
}

插件

// npm install --save-dev html-webpack-plugin 自动生成html文件
// npm install --save-dev clear-webpack-plugin 删除打包文件
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { ClearWebpackPlugin } = require('clrae-webpack-plugin');

plugins: [
    // 自动生成HTML文件
    new HtmlWebpackPlugin({ 
      // 引入html模板文件
      template: './src/index.html' 
    }),
    // 删除打包文件,HtmlWebpackPlugin重新生成文件
    new ClearWebpackPlugin()
],

环境变量

  // .env.development 文件:开发
  // .env.production  文件:生产
  "scripts": {
    "serve": "vue-cli-service serve",
    "build-dev": "vue-cli-service build --mode development",
    "build-pro": "vue-cli-service build --mode production",
    "build-alpha": "vue-cli-service build --mode alpha",
  },

webpackDevserve

 // // 自动打包,热加载,请求转发,代理(只能在测试环境上使用),模块热替换
 // webpackDevServe:不需要重新打包
     // 1. 自动打包
         // 配置命令:webpack内置命令启动项目
        "script":{
            "watch": "webpack --watck"
        }
        module.exports = {
          plugins:{
            new HtmlWebpackPlugin({ 
              // 引入html模板文件
              template: './src/index.html' ,
              cache: false
            }),
          }
        };
     //  2. 自动打包,热加载,请求转发
         // 配置启动命令
         "script":{
             // 自动打包
            "start": "webpack serve"
        }
         module.exports = {
          debServe: {
             // 自动打包 热加载
             //  webpack3: contentBase: './dist',
             "static""./dist",
             // 模块热替换,启动HMR:css不需要配置,,js需要配置
             "hot": true
            // open: true,   //是否自动打开浏览器
            port8080,      //启动端口号
            httpsfalse,    //是否开启https
            hotOnlyfalse,
            proxy: {         // 配置代理
              '/api': {
                target'http://www.xxxx/app', // 代理地址
                wstrue,
                changOrigintrue,  // 是否开启代理
                proxyTimeout: 3000, // 超时时间
                pathRewrite: {      // /api开头的请求会去到target下请求
                  '^/api'''       // 替换/api 为空字符
                }
              }
            },
          },
          plugins:{
            new HtmlWebpackPlugin({ 
              // 引入html模板文件
              template: './src/index.html' ,
              // 缓存
              cache: false
            }),
          }
        };
        
         // js热加载
         // 入口文件,中执行
         if (module.hot) {
            module.hot.accepy("./number.js", () => {
                // 获取dom元素
                const numberDiv = document.getElementById('number')
               // remove掉dom元素
                document.dody.removeChild(numberDiv)
                // 重新执行number方法,重新生成dom元素
                number()
           })
        }

babel处理ES6语法

// ES6语法转换为ES5语法
// npm install  babel-loader--save-dev
// npm install @babel/core --save-dev
// npm install @babel/preset-env --save-dev
// 兼容低版本浏览器:polyfill: npm install --save @babel/polyfill
// 在使用了ES6语法的js文件引入:import '@babel/polyfill'
module: {
    rules: {
        // 文件以js结尾的
        test: /\/js$/,
        include: /node_modules/,
        // 排除node_module文件下的js文件,依赖
        exclude: /node_modules/,
        use: {
            loader: "babel-loader",
            // opstions: ['@babel/preset--env']
             opstions: {
                ['@babel/preset--env'],
                {
                    // 配置@babel/polyfill, 在使用ES6语法文件引入import '@babel/polyfill'
                    useBuiltins: 'usage'
                }
            }
        }
    }
}

代码校验 eslint-webpack-plugin

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /.js$/,
        exclude: /node_modules/,
        loader: 'eslint-loader',
        options: {
          // eslint options (if necessary)
        },
      },
    ],
  },
  // ...
};

html-withimg-loader

我们在编译图片时,都是使用file-loaderurl-loader,这两个loader都是查找js文件里的相关图片资源,但是html里面的文件不会查找所以我们html里的图片也想打包进去,这时使用html-withimg-loader

// 如果打包出现img的src路径为`[Object Module]`,解决方案有
// 将file-loader降级到4.2.0
// 修改options参数esModule为false
module.exports = {
    module: {
        rules: [
            {
                test: /\.(png|jpg|jpeg)$/,
                use: {
                    loader: "file-loader",
                    options: {
                        name: "[name]_[hash:8].[ext]",
                        publicPath: "http://www.baidu.com",
                        esModule: false
                    }
                }
            },
            {
                test: /\.(png|jpeg|jpg)/,
                use: "html-withimg-loader"
            }
        ]
    }
}