webpack ... 待补充

151 阅读4分钟

webpack 配置

官网 www.webpackjs.com/concepts/
官网配置 webpack.js.org/configurati…

一、起步

  1. 我们选择局部安装 webpack webpack-cli

    • webpack 4.+ 需要安装 webpack-cli
    • npm i webpack webpack-cli
  2. 因为是局部安装的,可以在 package.json 里面配置 脚本命名

    "scripts": {
        "build": "webpack --mode development",
    }
    
    • 这样就可以运行 npm run build 来启用webpack了
  3. 我们需要新建入口文件,webpack默认入口文件是./src/index.js

    • 新建好后就可以运行 npm run build 来看看webpack为我们做了什么了
  4. webpack-dev-server

    • 起一个开发服务器
    • 用来访问打包好的 html、css、js
    • 配置
      • package.json
      "dev": "webpack-dev-server --mode development --config build/webpack.config.js",
      
    • 运行 npm run dev

二、webpack的配置文件

webpack 默认配置文件为根目录下的 webpack.config.js

  1. entry / output
    • 单入口 单出口
        entry: './src/index.js',  //默认的入口文件
        output: {   // 【不写 默认是 dist/main.js】
            path: path.resolve(__dirname,'dist'), // 输出目录 用到了 path模块需要导入 【默认不写就是 根目录/dist】
            filename: 'main.js' //输出文件名
        }
    
    • 多入口 多出口
        /*
        webpack 自带 变量
        name: 表示跟入口文件同名,入口文件为对象形式时,就是对象的key
        hash: 表示hash值 这个是全局hash (不合理,我们使用chunkHash代替)
        hash:5 表示截取前5位
        chunkHash: 根据文件不同生成的也不一样
        contentHash: 不怎么用 
        */
        entry: { // 多个入口
            home: './src/home.js',
            about: './src/about.js'
        },
        output: {
            path: path.resolve(__dirname,'dist'),
            filename: '[name].[hash:5].js'  // 【不写默认跟入口文件同名】
        }
    

三、配置一个基本的开发环境

www.npmjs.com/

const path = require('path')
module.exports = {
    entry: {
        index: './src/index.js'
    },
    output: {
        path: path.resolve(process.cwd(),'dist'),
        filename: '[name].[chunkHash:5].js'
    }
}

3.1 处理html

  1. html-webpack-plugin 自动打包html文件

3.2 处理 css

  1. css-loader

    • 使用css-loader 的时候 还需要安装 style-loader
      • css-loader 我们在入口js文件导入 css文件后 css-loader负责打包 把css文件整合到打包好的 js文件中
      • style-loader 负责吧打包好的js文件里的css 文件 在html文件中创建 style 标签并插入
    module.exports = {
        module: {
            rules: [
            {
                test: /\.css$/i,
                use: ['style-loader', 'css-loader'],
            },
            ],
        },
    };
    
  2. mini-css-extract-plugin

    • webpack 4.+ 起
    • 因为css-loader打包的 css文件都是插入到页面 style的内联样式,如果需要生成一个单独的外部css样式文件需要使用它来打包
  3. extract-text-webpack-plugin

    • webpack 4 以前
    • mini-css-extract-plugin
  4. less-loader

    • 安装 less-loader 还需要 安装 less
    • npm i less-loader less -S
  5. postcss-loader

    • 给样式自动加前缀,需要 autoprefixer 配合使用
    • 步骤
      1. npm install postcss-loader autoprefixer -S
      2. 需要在 css-loader之前使用,use里面是从下往上的顺序使用
          rules: [
              {
                  test: /\.less$/,  // 处理 less
                  use: [
                      MiniCssExtractPlugin.loader,
                      'css-loader',
                      'postcss-loader', // 自动添加前缀 还需配合 autoprefixer
                      'less-loader'
                  ],
              }
          ]
      
      1. 根目录下新建 postcss.config.js
      module.exports = {
          plugins: [
              require('autoprefixer')
          ]
      }
      
    • 结果
      ::-moz-placeholder {
          color: #aaa;
      }
      :-ms-input-placeholder {
          color: #aaa;
      }
      ::-ms-input-placeholder {
          color: #aaa;
      }
      ::placeholder {
          color: #aaa;
      }
      
    • 注意:
      • 对于flex 如果我们要让其自动加上前缀,则需要使用到browserslist; package.json里面加入
          "browserslist": [
            "cover 99.5%"
          ]
        
      • browserslist 调用的是 caniuse 里面的 api

3.3 处理图片资源

  • 只针对js里面 import的css里面用到的图片,html标签的图片不会进行处理
  1. file-loader
    • 直接拷贝图片资源
    • 使用的时候要注意打包后的路径变化
        {
            test: /\.(png|jpe?g|gif)$/i,
            use: [
                {
                    loader: 'file-loader',
                    options: {
                        name: 'static/images/[name].[ext]',
                        publicPath: '/'
                    },
                },
            ],
        }
    
  2. url-loader
    • 也可处理图片资源
    • 特点: 通过配置项来进行 图片 base64 转换处理
    {
        test: /\.(png|jpe?g|gif)$/i,
        use: [
            // 方法1: file-loader 处理图片资源
            // {
            //     loader: 'file-loader',
            //     options: {
            //         name: 'static/images/[name].[ext]',
            //         publicPath: '/'
            //     }
            // },
            // 方法2: url-loader 处理图片资源   base64 处理
            {
                loader: 'url-loader',
                options: {
                    limit: 1024*130,  // 图片大小没有超过 130kb 时 直接转成 base64 处理
                    // 下面两行时图片大小超过了 limit的值时的处理方式,把图片放在/static/images/图片名.图片拓展名
                    name: 'static/images/[name].[ext]',
                    publicPath: '/'
                }
            }
        ],
    },
    

3.4 拷贝文件资源

  1. copy-webpack-plugin
	const CopyPlugin = require('copy-webpack-plugin');

    new CopyPlugin({
        patterns: [
          {
            from: path.resolve(process.cwd(),'src/static'),
            to:path.resolve(process.cwd(),'dist/static')
          }
        ],
    }),

3.5 添加babel es6 转 es5

  1. babel-loader
    • $ npm install -D babel-loader @babel/core @babel/preset-env
    	rules: [
        	{
                test: /\.m?js$/,
                exclude: /(node_modules|bower_components)/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                }
            }
       ]
    

3.6 拆分webpack.config.js

  • 需要用到 webpack-merge
    • $ npm i webpack-merge
  • 我们 npm run buildnpm run dev 使用的是同一个webpack.config.js文件,现在对其拆分并把公共部分提取出来
    • webpack.dev.js
    • webpack.prod.js
    • webpack.common.js
    • webpack.config.js
  • 步骤
        // webpack.dev.js
        const common = require('./webpack.common.js')
        const { merge } = require('webpack-merge')
        module.exports = merge(common, {
            // 写 dev环境才需要的配置 , eg: 
            devServer: {
                port: 9000
            }
            ...
        })
    

四、一个webpack的配置

  1. package.json
{
  "name": "webpack-get-start",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "webpack  --env production --config build/webpack.config.js",
    "dev": "webpack-dev-server --env development --config build/webpack.config.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Bolo",
  "license": "MIT",
  "devDependencies": {
    "@babel/core": "^7.11.1",
    "@babel/preset-env": "^7.11.0",
    "babel-loader": "^8.1.0",
    "clean-webpack-plugin": "^3.0.0",
    "copy-webpack-plugin": "^6.0.3",
    "cross-env": "^7.0.2",
    "css-loader": "^4.2.1",
    "file-loader": "^6.0.0",
    "html-webpack-plugin": "^4.3.0",
    "mini-css-extract-plugin": "^0.10.0",
    "style-loader": "^1.2.1",
    "url-loader": "^4.1.0",
    "webpack": "^4.44.1",
    "webpack-cli": "^3.3.12",
    "webpack-dev-server": "^3.11.0"
  },
  "dependencies": {
    "autoprefixer": "^9.8.6",
    "less": "^3.12.2",
    "less-loader": "^6.2.0",
    "postcss-loader": "^3.0.0",
    "webpack-merge": "^5.1.1"
  },
  "browserslist": [
    "cover 99.5%"
  ]
}
  1. webpack.config.js
const commonConfig = require('./webpack.common.js');
const productionConfig = require('./webpack.prod.js');
const developmentConfig = require('./webpack.dev.js');
const { merge } = require('webpack-merge')

module.exports = env => {  // env 需要通过 package.json 传入
    console.log('boloooo',env)
    switch (env) {
        case 'development':
            return merge(commonConfig, developmentConfig);
        case 'production':
            return merge(commonConfig, productionConfig);
        default:
            throw new Error('No matching configuration was found!');
    }
}
  1. webpack.common.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const CopyPlugin = require('copy-webpack-plugin');

module.exports = {
    entry: {
        index: './src/index.js'
    },
    output: {
        path: path.resolve(process.cwd(), 'dist'),
        filename: '[name].[chunkHash:5].js'
    },
    plugins: [
        new HtmlWebpackPlugin({
            title: 'webpack - leaning',
            template: 'src/public/index.html'
        }),
        new CleanWebpackPlugin({
            cleanOneceBeforeBuildPatterns: ['./dist']
        }),
        new CopyPlugin({ 
            patterns: [
                {
                    from: path.resolve(process.cwd(), 'src/static'),
                    to: path.resolve(process.cwd(), 'dist/static')
                },
            ]
        }),
    ],
    module: {
        rules: [
            // 图片资源的处理 common
            {
                test: /\.(png|jpe?g|gif)$/i,
                use: [
                    {
                        loader: 'url-loader',
                        options: {
                            limit: 1024 * 130,
                            name: 'images/[name].[ext]',
                            publicPath: '/'
                        }
                    }
                ],
            },
            // babel  common
            {
                test: /\.m?js$/,
                exclude: /(node_modules|bower_components)/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                }
            }
        ]
    }
}
  1. webpack.dev.js

module.exports =  {
    mode: 'development',
    module: {
        rules: [
            // 处理 css 文件
            {
                test: /\.css$/,
                use: [
                    'style-loader',
                    'css-loader',
                ],
            },
            // 处理 less 文件  mode:dev  -- style-loader
            {
                test: /\.less$/,
                use: [
                    'style-loader',
                    'css-loader',
                    'less-loader'
                ],
            }
        ]
    },
    devServer: {
        port: 9000,
        open: true
    }
}
  1. webpack.prod.js
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
    mode: 'production',
    plugins: [
        new MiniCssExtractPlugin({
            filename: 'css/[name].css'
        })
    ],
    module: {
        rules: [
            // 处理 css 文件
            {
                test: /\.css$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'postcss-loader'
                ],
            },
            // 处理 less 文件
            {
                test: /\.less$/,
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'postcss-loader', // 自动添加前缀 还需配合 autoprefixer
                    'less-loader'
                ],
            }
        ]
    },

}

补充

1. 什么是hash值

通过一定的哈希算bai法(典型的有MD5,SHA-1等),将一段较长的数据映射为较zhi短小的数据,这段小数据就是大数据的哈希值。他有这样一个特点,他是唯一的,一旦大数据发生了变化,哪怕是一个微小的变化,他的哈希值也会发生变化。

2. package.json 里面启动webpack时的配置

  1. mode
    • 模式 development/production
    • --mode development
  2. config
    • 指定webpack的配置文件路径
    • --config configs/webpack.config.js
    • 注意: 如果改变了配置文件的路径, output 时如果用 __dirname 就会指定 dist 在当前目录下了,如果还需要指定在根目录下,需要这样写
      • path: path.resolve(process.cwd(),'dist')
  3. env

3. 启动时给某变量赋值,并可在webpack.config.js 访问

"dev": "webpack-dev-server --config build/webpack.config.js",
  1. 方法1 : 使用 --env 值
    • "dev": "webpack-dev-server --env development --config build/webpack.js",
      • console.log(env) // 'development'
    • "dev": "webpack-dev-server --env.NODE_ENV development --config build/webpack.js",
      • console.log(env) // {NODE_ENV:'development'}
  2. 方法2: 使用 cross-env 第三方依赖
    • 安装依赖
    • 传入 NODE_ENV=development
      "scripts": {
          "start": "cross-env NODE_ENV=development webpack-dev-server --config ./build/webpack.config.js",
          "build": "cross-env NODE_ENV=production webpack --config ./build/webpack.config.js"
      },
      
    • webpack.config.js 获取的时候可以使用 process.env.NODE_ENV 去获取
      • devtool: process.env.NODE_ENV === 'production' ? false : 'inline-source-map',