1.什么是webpack? #

1.1 webpack #

1.2 webpack-cli #

1.3 安装 #

npm install webpack webpack-cli  webpack-dev-server style-loader css-loader html-webpack-plugin cross-env mini-css-extract-plugin less less-loader postcss postcss-loader autoprefixer @babel/core @babel/preset-env babel-loader typescript ts-loader @babel/preset-typescript  eslint eslint-webpack-plugin eslint-config-standard eslint-plugin-promise eslint-plugin-import eslint-plugin-node @typescript-eslint/eslint-plugin --save

2. webpack打包 #

2.1 entry #

2.1.1 webpack.config.js #

webpack.config.js

module.exports = {
  mode:'development',
  devtool:false,
  entry: './src/index.js',
  /*
  entry: ['./src/entry1.js','./src/entry2.js'],
  entry:{
    app: './src/index.js',
  }
  */
};

2.1.2 package.json #

package.json

{
  "scripts": {
    "build": "webpack"
  }
}

2.1.3 src\index.js #

src\index.js

console.log('index');

2.2 output #

2.2.1 webpack.config.js #

webpack.config.js

+const path = require('path');
module.exports = {
  mode:'development',
  devtool:false,
  entry: './src/index.js',
+ output: {
+     path: path.resolve(__dirname, 'dist'),
+     filename: 'main.js'
+ }
};

2.3 loader #

2.3.1 src\index.js #

src\index.js

+import './index.css';
console.log('index');

2.3.2 src\index.css #

src\index.css

body{
  color: red;
}

2.3.3 webpack.config.js #

const path = require('path');
module.exports = {
  mode:'development',
  entry: './src/index.js',
  output: {
      path: path.resolve(__dirname, 'dist'),
      filename: 'main.js'
  },
+ module: {
+   rules: [
+     { test: /\.css$/, use: ['style-loader','css-loader']}
+   ]
+ }
};

2.4 插件 #

2.4.1 webpack.config.js #

webpack.config.js

const path = require('path');
+const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
  mode:'development',
  entry: './src/index.js',
  output: {
      path: path.resolve(__dirname, 'dist'),
      filename: 'main.js'
  },
  module: {
    rules: [
      { test: /\.css$/, use: ['style-loader','css-loader']}
    ]
  },
+ plugins: [
+   new HtmlWebpackPlugin({template: './src/index.html'})
+ ]
};

2.4.2 src\index.html #

src\index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>webpack</title>
</head>
<body>
</body>
</html>

2.5 webpack-dev-server #

2.5.1 webpack.config.js #

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
  mode:'development',
  entry: './src/index.js',
  output: {
      path: path.resolve(__dirname, 'dist'),
      filename: 'main.js'
  },
+ devServer: {
+   static: path.join(__dirname, 'public'),
+   compress: true,
+   host:'localhost',
+   port: 9000,
+   open:true,
+   hot:true,
+   historyApiFallback: true,
+   watchFiles: [
+     "src/**/*.js",
+     "src/**/*.css"
+   ]
+ },
  module: {
    rules: [
      { test: /\.css$/, use: ['style-loader','css-loader']}
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({template: './src/index.html'})
  ]
};

2.5.2 package.json #

package.json

{
  "scripts": {
    "build": "webpack",
+   "dev": "webpack serve"
  }
}

3. 处理CSS资源 #

3.1 package.json #

package.json

{
  "scripts": {
+   "build": "cross-env NODE_ENV=production  webpack",
+   "dev": "cross-env NODE_ENV=development  webpack serve"
  }
}

3.2 webpack.config.js #

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
  mode:'development',
  devtool:false,
  entry: './src/index.js',
  output: {
      path: path.resolve(__dirname, 'dist'),
      filename: 'main.js'
  },
  devServer: {
    static: path.join(__dirname, 'public'),
    compress: true,
    port: 9000
  },
  module: {
    rules: [
      { test: /\.css$/, use: [
+       (process.env.NODE_ENV === 'development' ?
+         'style-loader' :
+         MiniCssExtractPlugin.loader)
        ,'css-loader']}
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({template: './src/index.html'}),
+   new MiniCssExtractPlugin(),
  ]
};

4. 使用预处理器 #

4.1 src\index.js #

src\index.js

import './index.css';
+import './index.less';
console.log('index');

4.2 src\index.less #

src\index.less

@color:red;
body{
    color: @color;
}

4.3 webpack.config.js #

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
  mode: 'development',
  devtool: false,
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'main.js'
  },
  devServer: {
    static: path.join(__dirname, 'public'),
    compress: true,
    port: 9000
  },
  module: {
    rules: [
      {
        test: /\.css$/, use: [
          (process.env.NODE_ENV === 'development' ?
            'style-loader' :
            MiniCssExtractPlugin.loader),
           'css-loader']
      },
+     {
+       test: /\.less$/, use: [
+         (process.env.NODE_ENV === 'development' ?
+           'style-loader' :
+           MiniCssExtractPlugin.loader),
+         'css-loader',
+         'less-loader'
+       ]
+     }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({ template: './src/index.html' }),
    new MiniCssExtractPlugin(),
  ]
};

5. PostCSS #

5.1 webpack.config.js #

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
  mode: 'development',
  devtool: false,
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'main.js'
  },
  devServer: {
    static: path.join(__dirname, 'public'),
    compress: true,
    port: 9000
  },
  module: {
    rules: [
      {
        test: /\.css$/, 
        use: [
          (process.env.NODE_ENV === 'development' ?
            'style-loader' :
            MiniCssExtractPlugin.loader),
            'css-loader',
+           "postcss-loader"
          ]
      },
      {
        test: /\.less$/, 
        use: [
          (process.env.NODE_ENV === 'development' ?
            'style-loader' :
            MiniCssExtractPlugin.loader),
          'css-loader',
+         "postcss-loader",
          'less-loader'
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({ template: './src/index.html' }),
    new MiniCssExtractPlugin(),
  ]
};

5.2 postcss.config.js #

postcss.config.js

module.exports = {
    plugins: [
        require("autoprefixer")
    ]
};

5.3 .browserslistrc #

.browserslistrc

# Browsers that we support

last 2 versions
> 1%
iOS 7
last 3 iOS versions

6. Babel #

6.1 webpack.config.js #

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
  mode: 'development',
  devtool: false,
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'main.js'
  },
  devServer: {
    static: path.join(__dirname, 'public'),
    compress: true,
    port: 9000
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        use: [
          {
+           loader: 'babel-loader'
          }
        ]
      },
      {
        test: /\.css$/, use: 
          [
          (process.env.NODE_ENV === 'development' ?
            'style-loader' :
            MiniCssExtractPlugin.loader),
            'css-loader',
            "postcss-loader"
          ]
      },
      {
        test: /\.less$/, 
        use: [
          (process.env.NODE_ENV === 'development' ?
            'style-loader' :
            MiniCssExtractPlugin.loader),
          'css-loader',
          "postcss-loader",
          'less-loader'
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({ template: './src/index.html' }),
    new MiniCssExtractPlugin(),
  ]
};

6.2 .babelrc #

.babelrc

{
    "presets": [
      [
        "@babel/preset-env",
        {
          "targets": {
            "ie": "11"
          }
        }
      ]
    ]
  }

6.3 src\index.js #

src\index.js

let sum = (a,b)=>a+b;
console.log(sum(1,2));

7. TypeScript #

7.1 ts-loader #

7.1.1 webpack.config.js #

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
  mode: 'development',
  devtool: false,
+ entry: './src/index.ts',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'main.js'
  },
  devServer: {
    static: path.join(__dirname, 'public'),
    compress: true,
    port: 9000
  },
+ resolve: {
+   extensions: ['.ts', '.js'],
+ },
  module: {
    rules: [
+     {
+       test: /\.ts$/,
+       use: 'ts-loader',
+       exclude: /node_modules/
+     },
      {
        test: /\.js$/,
        use: [
          {
            loader: 'babel-loader'
          }
        ]
      },
      {
        test: /\.css$/, use: 
          [
          (process.env.NODE_ENV === 'development' ?
            'style-loader' :
            MiniCssExtractPlugin.loader),
            'css-loader',
            "postcss-loader"
          ]
      },
      {
        test: /\.less$/, 
        use: [
          (process.env.NODE_ENV === 'development' ?
            'style-loader' :
            MiniCssExtractPlugin.loader),
          'css-loader',
          "postcss-loader",
          'less-loader'
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({ template: './src/index.html' }),
    new MiniCssExtractPlugin(),
  ]
};

7.1.2 tsconfig.json #

tsconfig.json

{
    "compilerOptions": {
      "noImplicitAny": true,
      "moduleResolution": "node"
    }
  }

7.1.3 src\index.ts #

src\index.ts


7.2 babel-loader #

7.2.1 webpack.config.js #

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
  mode: 'development',
  devtool: false,
  entry: './src/index.ts',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'main.js'
  },
  devServer: {
    static: path.join(__dirname, 'public'),
    compress: true,
    port: 9000
  },
  resolve: {
    extensions: ['.ts', '.js'],
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: 
+       [
+         {
+           loader: 'babel-loader',
+           options: {
+             presets: ['@babel/preset-typescript']
+           }
+         }
+       ],
        exclude: /node_modules/
      },
      {
        test: /\.js$/,
        use: [
          {
            loader: 'babel-loader'
          }
        ]
      },
      {
        test: /\.css$/, use: 
          [
          (process.env.NODE_ENV === 'development' ?
            'style-loader' :
            MiniCssExtractPlugin.loader),
            'css-loader',
            "postcss-loader"
          ]
      },
      {
        test: /\.less$/, 
        use: [
          (process.env.NODE_ENV === 'development' ?
            'style-loader' :
            MiniCssExtractPlugin.loader),
          'css-loader',
          "postcss-loader",
          'less-loader'
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({ template: './src/index.html' }),
    new MiniCssExtractPlugin(),
  ]
};

8. ESLint #

8.1 webpack.config.js #

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
+const ESLintPlugin = require('eslint-webpack-plugin')
module.exports = {
  mode: 'development',
  devtool: false,
  entry: './src/index.ts',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'main.js'
  },
  devServer: {
    static: path.join(__dirname, 'public'),
    compress: true,
    port: 9000
  },
  resolve: {
    extensions: ['.ts', '.js'],
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        use: 
        [
          {
            loader: 'babel-loader',
            options: {
              presets: ['@babel/preset-typescript']
            }
          }
        ],
        exclude: /node_modules/
      },
      {
        test: /\.js$/,
        use: [
          {
            loader: 'babel-loader'
          }
        ]
      },
      {
        test: /\.css$/, use: 
          [
          (process.env.NODE_ENV === 'development' ?
            'style-loader' :
            MiniCssExtractPlugin.loader),
            'css-loader',
            "postcss-loader"
          ]
      },
      {
        test: /\.less$/, 
        use: [
          (process.env.NODE_ENV === 'development' ?
            'style-loader' :
            MiniCssExtractPlugin.loader),
          'css-loader',
          "postcss-loader",
          'less-loader'
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({ template: './src/index.html' }),
    new MiniCssExtractPlugin(),
+   new ESLintPlugin({ extensions: ['.js', '.ts'] })
  ]
};

8.2 .eslintrc #

.eslintrc

{
    "parser": "@typescript-eslint/parser",
    "plugins": ["@typescript-eslint"],
    "extends": ["plugin:@typescript-eslint/recommended"]
}

8.3 src\index.ts #

src\index.ts

let sum = (a:number,b:number)=>a+b;
console.log(sum(1,2));

9.图像 #

9.1 asset-modules #

9.2 webpack.config.js #

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const ESLintPlugin = require('eslint-webpack-plugin')
module.exports = {
  mode: 'development',
  devtool: false,
  entry: './src/index.ts',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'main.js'
  },
  devServer: {
    static: path.join(__dirname, 'public'),
    compress: true,
    port: 9000
  },
  resolve: {
    extensions: ['.ts', '.js'],
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        use:
          [
            {
              loader: 'babel-loader',
              options: {
                presets: ['@babel/preset-typescript']
              }
            }
          ],
        exclude: /node_modules/
      },
      {
        test: /\.js$/,
        use: [
          {
            loader: 'babel-loader'
          }
        ]
      },
      {
        test: /\.css$/, use:
          [
            (process.env.NODE_ENV === 'development' ?
              'style-loader' :
              MiniCssExtractPlugin.loader),
            'css-loader',
            "postcss-loader"
          ]
      },
      {
        test: /\.less$/,
        use: [
          (process.env.NODE_ENV === 'development' ?
            'style-loader' :
            MiniCssExtractPlugin.loader),
          'css-loader',
          "postcss-loader",
          'less-loader'
        ]
      },
+     {
+       test: /\.(png)$/,
+       type: 'asset/resource'
+     },
+     {
+       test: /\.(jpg)$/,
+       type: "asset/inline"
+     },
+     {
+       test: /\.(bmp)$/,
+       type: "asset",
+       parser: {
+         dataUrlCondition: {
+           maxSize: 1024
+         }
+       }
+     },
      {
        test: /\.svg$/i,
       type: "asset/source"
      },
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({ template: './src/index.html' }),
    new MiniCssExtractPlugin(),
    new ESLintPlugin({ extensions: ['.js', '.ts'] })
  ]
};

9.2 压缩图片 #

9.2.1 安装 #

cnpm install image-webpack-loader --save

9.2.2 webpack.config.js #

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const ESLintPlugin = require('eslint-webpack-plugin')
module.exports = {
  mode: 'development',
  devtool: false,
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'main.js'
  },
  devServer: {
    static: path.join(__dirname, 'public'),
    compress: true,
    port: 9000
  },
  resolve: {
    extensions: ['.ts', '.js'],
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        use:
          [
            {
              loader: 'babel-loader',
              options: {
                presets: ['@babel/preset-typescript']
              }
            }
          ],
        exclude: /node_modules/
      },
      {
        test: /\.js$/,
        use: [
          {
            loader: 'babel-loader'
          }
        ]
      },
      {
        test: /\.css$/, use:
          [
            (process.env.NODE_ENV === 'development' ?
              'style-loader' :
              MiniCssExtractPlugin.loader),
            'css-loader',
            "postcss-loader"
          ]
      },
      {
        test: /\.less$/,
        use: [
          (process.env.NODE_ENV === 'development' ?
            'style-loader' :
            MiniCssExtractPlugin.loader),
          'css-loader',
          "postcss-loader",
          'less-loader'
        ]
      },
      {
        test: /\.(png)$/,
        type: 'asset/resource'
      },
      {
        test: /\.(jpg)$/,
        type: "asset/inline"
      },
      {
        test: /\.(bmp)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            maxSize: 1024
          }
        }
      },
      {
        test: /\.svg$/i,
       type: "asset/source"
      },
+     {
+       // 匹配文件的正则表达式,这里表示匹配JPG、PNG、GIF和SVG格式的图片文件
+       test: /\.(jpe?g|png|gif|svg)$/i, 
+       use: [
+         {
+            // 使用image-webpack-loader对图片进行优化和压缩
+           loader: 'image-webpack-loader',
+           options: {
+             // 是否禁用图片优化和压缩
+             disable: process.env.NODE_ENV === 'development', 
+             mozjpeg: {
+               progressive: true, // 是否开启渐进式JPEG,可以有效提升JPEG图片加载速度
+               quality: 65 // 压缩JPEG图片的质量,取值范围为0到100,值越大质量越好但文件越大
+             },
+             optipng: {
+               enabled: true // 是否开启PNG图片的优化,可以有效提升PNG图片加载速度
+             },
+             pngquant: {
+               // 压缩PNG图片的质量范围,取值范围为0到1,值越大质量越好但文件越大
+               // 第一个数字表示压缩质量的下限,第二个数字表示压缩质量的上限
+               quality: [0.65, 0.9], 
+               speed: 4 // 压缩PNG图片的速度,取值范围为1到10,值越大速度越快但质量越低
+             },
+             svgo: {
+               plugins: [ // 压缩SVG图片的插件列表,这里包含removeViewBox和cleanupIDs两个插件
+                 { //用于删除SVG图片中的viewBox属性
+                   //viewBox属性是用来指定SVG视口范围的,它的值是一个矩形框的坐标和宽高
+                   removeViewBox: false
+                 },
+                 { //用于删除SVG图片中的无用ID属性
+                   cleanupIDs: true
+                 }
+               ]
+             },
+             gifsicle: {
+               interlaced: true // 是否开启GIF图片的隔行扫描,可以有效提升GIF图片加载速度
+             }
+           }
+         }
+       ]
+     }      
   ]
  },
  plugins: [
    new HtmlWebpackPlugin({ template: './src/index.html' }),
    new MiniCssExtractPlugin(),
    //new ESLintPlugin({ extensions: ['.js', '.ts'] })
  ]
};

9.3 响应式图片 #

9.3.1 安装 #

cnpm i responsive-loader sharp --save

9.3.2 webpack.config.js #

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const ESLintPlugin = require('eslint-webpack-plugin')
module.exports = {
  mode: 'development',
  devtool: false,
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'main.js'
  },
  devServer: {
    static: path.join(__dirname, 'public'),
    compress: true,
    port: 9000
  },
  resolve: {
    extensions: ['.ts', '.js'],
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        use:
          [
            {
              loader: 'babel-loader',
              options: {
                presets: ['@babel/preset-typescript']
              }
            }
          ],
        exclude: /node_modules/
      },
      {
        test: /\.js$/,
        use: [
          {
            loader: 'babel-loader'
          }
        ]
      },
      {
        test: /\.css$/, use:
          [
            (process.env.NODE_ENV === 'development' ?
              'style-loader' :
              MiniCssExtractPlugin.loader),
            'css-loader',
            "postcss-loader"
          ]
      },
      {
        test: /\.less$/,
        use: [
          (process.env.NODE_ENV === 'development' ?
            'style-loader' :
            MiniCssExtractPlugin.loader),
          'css-loader',
          "postcss-loader",
          'less-loader'
        ]
      },
/*       {
        test: /\.(png)$/,
        type: 'asset/resource'
      },
      {
        test: /\.(jpg)$/,
        type: "asset/inline"
      },
      {
        test: /\.(bmp)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            maxSize: 1024
          }
        }
      },
      {
        test: /\.svg$/i,
       type: "asset/source"
      },
      {
        // 匹配文件的正则表达式,这里表示匹配JPG、PNG、GIF和SVG格式的图片文件
        test: /\.(jpe?g|png|gif|svg)$/i, 
        use: [
          {
             // 使用image-webpack-loader对图片进行优化和压缩
            loader: 'image-webpack-loader',
            options: {
              // 是否禁用图片优化和压缩
              disable: process.env.NODE_ENV === 'development', 
              mozjpeg: {
                progressive: true, // 是否开启渐进式JPEG,可以有效提升JPEG图片加载速度
                quality: 65 // 压缩JPEG图片的质量,取值范围为0到100,值越大质量越好但文件越大
              },
              optipng: {
                enabled: true // 是否开启PNG图片的优化,可以有效提升PNG图片加载速度
              },
              pngquant: {
                // 压缩PNG图片的质量范围,取值范围为0到1,值越大质量越好但文件越大
                // 第一个数字表示压缩质量的下限,第二个数字表示压缩质量的上限
                quality: [0.65, 0.9], 
                speed: 4 // 压缩PNG图片的速度,取值范围为1到10,值越大速度越快但质量越低
              },
              svgo: {
                plugins: [ // 压缩SVG图片的插件列表,这里包含removeViewBox和cleanupIDs两个插件
                  { //用于删除SVG图片中的viewBox属性
                    //viewBox属性是用来指定SVG视口范围的,它的值是一个矩形框的坐标和宽高
                    removeViewBox: false
                  },
                  { //用于删除SVG图片中的无用ID属性
                    cleanupIDs: true
                  }
                ]
              },
              gifsicle: {
                interlaced: true // 是否开启GIF图片的隔行扫描,可以有效提升GIF图片加载速度
              }
            }
          }
        ]
      }, */
+     {
+                test: /\.(jpe?g|png)$/i,
+               //oneOf是一个优化选项,用于提高打包的速度
+               oneOf:[
+                   {
+                       //resourceQuery是一个用于匹配请求资源的URL中查询字符中
+                       resourceQuery:/sizes/,
+                       use:[
+                           {
+                            loader:'responsive-loader',
+                            options:{
+                               sizes:[300,600,1024],
+                               adapter:require('responsive-loader/sharp')
+                            }
+                           }
+                        ]
+                   },
+                   {
+                       type: 'asset/resource',
+                   }
+               ]
+           }   
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({ template: './src/index.html' }),
    new MiniCssExtractPlugin(),
    //new ESLintPlugin({ extensions: ['.js', '.ts'] })
  ]
};

9.3.2 src\index.js #

src\index.js

import responsiveImg from './images/bg.png?sizes[]=300,sizes[]=600,sizes[]=1024';
console.log(bg);
let image = new Image();
image.srcset = responsiveImg.srcSet;
image.sizes = `(min-width: 1024) 1024px,100vw`;
document.body.appendChild(image);

9.4 雪碧图 #

9.4.1 webpack.config.js #

webpack.config.js

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const ESLintPlugin = require('eslint-webpack-plugin')
const SpritesmithPlugin = require('webpack-spritesmith');

module.exports = {
  mode: 'development',
  devtool: false,
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'main.js'
  },
  devServer: {
    static: path.join(__dirname, 'public'),
    compress: true,
    port: 9000
  },
  resolve: {
    extensions: ['.ts', '.js'],
  },
  module: {
    rules: [
      {
        test: /\.ts$/,
        use:
          [
            {
              loader: 'babel-loader',
              options: {
                presets: ['@babel/preset-typescript']
              }
            }
          ],
        exclude: /node_modules/
      },
      {
        test: /\.js$/,
        use: [
          {
            loader: 'babel-loader'
          }
        ]
      },
      {
        test: /\.css$/, use:
          [
            (process.env.NODE_ENV === 'development' ?
              'style-loader' :
              MiniCssExtractPlugin.loader),
            'css-loader',
            "postcss-loader"
          ]
      },
      {
        test: /\.less$/,
        use: [
          (process.env.NODE_ENV === 'development' ?
            'style-loader' :
            MiniCssExtractPlugin.loader),
          'css-loader',
          "postcss-loader",
+         {
+             loader:'less-loader',
+             options:{
+                 lessOptions:{
+                     paths:[
+                         path.resolve(__dirname,'src/spritesmith-generated')
+                     ]
+                 }
+             }
+         }
        ]
      },
      /*  {
        test: /\.(png)$/,
        type: 'asset/resource'
      },
      {
        test: /\.(jpg)$/,
        type: "asset/inline"
      }, */
      {
        test: /\.(bmp)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            maxSize: 1024
          }
        }
      },
      {
        test: /\.svg$/i,
        type: "asset/source"
      },
       {
        // 匹配文件的正则表达式,这里表示匹配JPG、PNG、GIF和SVG格式的图片文件
        test: /\.(jpe?g|png|gif|svg)$/i, 
        use: [
          {
             // 使用image-webpack-loader对图片进行优化和压缩
            loader: 'image-webpack-loader',
            options: {
              // 是否禁用图片优化和压缩
              disable: process.env.NODE_ENV === 'development', 
              mozjpeg: {
                progressive: true, // 是否开启渐进式JPEG,可以有效提升JPEG图片加载速度
                quality: 65 // 压缩JPEG图片的质量,取值范围为0到100,值越大质量越好但文件越大
              },
              optipng: {
                enabled: true // 是否开启PNG图片的优化,可以有效提升PNG图片加载速度
              },
              pngquant: {
                // 压缩PNG图片的质量范围,取值范围为0到1,值越大质量越好但文件越大
                // 第一个数字表示压缩质量的下限,第二个数字表示压缩质量的上限
                quality: [0.65, 0.9], 
                speed: 4 // 压缩PNG图片的速度,取值范围为1到10,值越大速度越快但质量越低
              },
              svgo: {
                plugins: [ // 压缩SVG图片的插件列表,这里包含removeViewBox和cleanupIDs两个插件
                  { //用于删除SVG图片中的viewBox属性
                    //viewBox属性是用来指定SVG视口范围的,它的值是一个矩形框的坐标和宽高
                    removeViewBox: false
                  },
                  { //用于删除SVG图片中的无用ID属性
                    cleanupIDs: true
                  }
                ]
              },
              gifsicle: {
                interlaced: true // 是否开启GIF图片的隔行扫描,可以有效提升GIF图片加载速度
              }
            }
          }
        ]
      },
     {
       test: /\.(jpe?g|png)$/i,
       oneOf:[
           {
             resourceQuery: /sizes?/,
             use: [
               {
                 loader: 'responsive-loader',
                 options: {
                   adapter: require('responsive-loader/sharp'),
                 },
               },
             ]
           },
           {
             type:'asset/resource',
           }
       ]
     },     
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({ template: './src/index.html' }),
    new MiniCssExtractPlugin(),
    //new ESLintPlugin({ extensions: ['.js', '.ts'] })
+   new WebpackSpritesmith({
+   src:{//指定输入的文件
+       cwd:path.resolve(__dirname,'src/images/icons'),
+       glob:'**/*.png'
+   },
+   target:{//指定输出的文件路径
+       image:path.resolve(__dirname,'src/spritesmith-generated/sprite.png'),
+       css:path.resolve(__dirname,'src/spritesmith-generated/sprite.less'),
+   },
+   apiOptions:{
+       cssImageRef: "sprite.png"
+   },
+   spritesmithOptions: {
+       algorithm: 'top-down',
+       padding: 10
+     }
+   })
  ]
};

9.4.2 src\index.js #

src\index.js

import './icons.less'

9.4.3 icons.less #

src\icons.less

@import 'sprite.less';
.icon-twitter {
    .sprite(@twitter);
}
.icon-facebook  {
    .sprite(@facebook);
}
.icon-github  {
    .sprite(@github);
}

10.entry 配置 #

10.1 字符串形式 #

module.exports = {
  entry: './src/index.js'
};

10.2函数形式 #

module.exports = {
  entry: {
    app:()=>'./src/app.js'
  }
};

10.3 数组形式 #

module.exports = {
  entry: ['./src/app.js', './src/vendor.js']
};

10.4 对象形式 #

10.4.1 dependOn #

10.4.1.1 webpack.config.js #

webpack.config.js

module.exports = {
  mode: 'development',
  devtool: false,
  entry:{
+   vendor:"./src/vendor.js",
+   main: { import: "./src/index.js", dependOn: "vendor" }
  }
}
10.4.1.2 src\index.js #

src\index.js

import {vendor} from './vendor.js';
console.log(vendor);
10.4.1.3 src\vendor.js #

src\vendor.js

export const vendor = 'vendor';

10.4.2 runtime #

10.4.2.1 webpack.config.js #

webpack.config.js

module.exports = {
  mode: 'development',
  devtool: false,
  entry:{
+   vendor:{ import: "./src/vendor.js", runtime: "runtime-vendor" },
+   main: { import: "./src/index.js", runtime: "runtime-main" }
  }
}

10.5 output #

10.5.1 webpack.config.js #

webpack.config.js

module.exports = {
  mode: 'development',
  devtool: false,
  entry:"./src/index.js",
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: '[name].js',
+   publicPath:'/',
+   clean:true,
+   chunkLoading:'jsonp'
  }
}

10.5.2 src\index.js #

src\index.js

import('./vendor').then(res=>console.log(res))

11. 服务器代理 #

如果你有单独的后端开发服务器 API,并且希望在同域名下发送 API 请求 ,那么代理某些 URL 会很有用。

11.1 不修改路径 #

devServer: {
  proxy: {
    "/api": 'http://localhost:3000'
  }
}

11.2 修改路径 #

devServer: {
  proxy: {
      "/api": {
       target: 'http://localhost:3000',
       pathRewrite:{"^/api":""}        
      }            
  }
}

11.3 onBeforeSetupMiddleware #

11.4 webpack-dev-middleware #

webpack-dev-middleware就是在 Express 中提供 webpack-dev-server 静态服务能力的一个中间件

npm install webpack-dev-middleware --save-dev
const express = require('express');
const app = express();
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackOptions = require('./webpack.config');
webpackOptions.mode = 'development';
const compiler = webpack(webpackOptions);
app.use(webpackDevMiddleware(compiler, {}));
app.listen(3000);