导航


HTML

CSS

JavaScript

浏览器 & 网络

版本管理

框架

构建工具

TypeScript

性能优化

软实力

算法

UI、组件库

Node

业务技能

针对性攻坚

AI


webpack本质目的

目录结构

Untitled

plugins and loaders

webpack.config.js 配置文件

const { resolve } = require('path');
const autoprefixer = require('autoprefixer');
const HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
  // 模式 开发 生产
  mode: 'development',
  // 生成 source-map, 方便调试
  devtool: 'source-map',
  // 优化: 禁止压缩
  optimization: {
    minimize: false
  },
  // 入口文件
  entry: {
    // __dirname: 当前项目目录下
    index: resolve(__dirname, './src/js/index.js'),
    detail: resolve(__dirname, './src/js/detail.js'),
    collections: resolve(__dirname, './src/js/collections.js')
  },
  output: {
    // 输出到 dist 目录下的 js 文件夹
    path: resolve(__dirname, './dist/js'),
    // 文件名称: [name] 入口文件名称
    filename: 'js/[name].js'
  },
  // 模块配置
  module: {
    // 模块匹配规则
    rules: [
      // 处理 es6
      {
        test: /\\.js$/,
        loader: 'babel-loader',
        // 排除 node_modules
        exclude: resolve(__dirname, 'node_modules'),
        query: {
          // 预设
          'presets': ['latest']
        }
      },
      // 处理模板文件
      {
        test: /\\.tpl$/,
        loader: 'ejs-loader'
      },
      // 处理 css 文件
      {
        test: /\\.css$/,
        use: [
          // 从下往上处理,先加兼容前缀,再经过,最后放进 html 内联样式
          'style-loader',
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              plugins: function() {
                // 兼容最近五个版本
                return [autoprefixer('last 5 versions')]
              }
            }
          }
        ]
      },
      // 处理 scss 文件
      {
        test: /\\.scss$/,
        use: [
          'style-loader',
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              plugins: function() {
                return [autoprefixer('last 5 versions')]
              }
            }
          },
          'sass-loader'
        ]
      },
      // 处理图片和文字
      {
        test: /\\.(jpg|jpeg|png|gif|ico|woff|eot|svg|ttf)$/i,
        // 1024以下直接处理成base64 、name为img下图片的name-hash16位.拓展名
        loaders: 'url-loader?limit=1024&name=img/[name]-[hash:16].[ext]'
      }
    ]
  },
  // 插件配置
  plugins: [
    new HtmlWebpackPlugin({
      filename: 'index.html',
      template: resolve(__dirname, './src/index.html'),
      title: '新闻头条',
      // chunks 是 块儿 的意思,也就是 js 文件和文件夹的意思
      chunksSortMode: 'manual', // 按照下面 chunks 中数组顺序引入脚本文件
      chunks: ['index'], // 和 entry 的文件名匹配
      // 譬如 index.html 会引入 src/js/ 下的多个脚本文件,
      // 而脚本之间是有依赖顺序的,所以需要告诉 webpack,让它按照我 chunks 数组的顺序来引入 js 文件
      excludeChunks: ['node_modules'], // 排除 node_modules
      hash: true, // 文件名后缀带hash,缓存用
      minify: {
        removeComments: true, // 删除注释
        collapseWhitespace: true, // 空格换行去掉
      }
    }),
    new HtmlWebpackPlugin({
      filename: 'detail.html',
      template: resolve(__dirname, './src/detail.html'),
      title: '新闻详情',
      chunks: ['detail'],
      chunksSortMode: 'manual',
      excludeChunks: ['node_modules'],
      hash: true,
      minify: {
        removeComments: true,
        collapseWhitespace: true
      }
    }),
    new HtmlWebpackPlugin({
      filename: 'collections.html',
      template: resolve(__dirname, './src/collections.html'),
      title: '我的新闻',
      chunks: ['collections'],
      chunksSortMode: 'manual',
      excludeChunks: ['node_modules'],
      hash: true,
      minify: {
        removeComments: true,
        collapseWhitespace: true
      }
    })
  ],
  // 开发服务器的配置
  devServer: {
    watchOptions: {
      ignored: /node_modules/
    },
    open: true,
    host: 'localhost',
    port: 3000
  }
}

项目组件化与模块化

webpack.config.js

const path = require('path');
const autoprefixer = require('autoprefixer');
const uglify = require('uglifyjs-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const miniCssExtractPlugin = require('mini-css-extract-plugin');

const config = {
  // 模式 开发 生产
  mode: 'development',
  externals: {
    'vue': 'Vue'
  },
  // 入口
  entry: {
    index: path.resolve(__dirname, './src/js/index.js')
  },
  // 出口
  output: {
    path: path.resolve(__dirname, './dist'),
    filename: 'js/[name].js'
  },
  // 模块配置
  module: {
    // 模块匹配规则
    rules: [
      // js es6+ 转 es5
      {
        test: /\\.js$/,
        loader: 'babel-loader',
        exclude: path.resolve(__dirname, 'node_modules'),
        query: {
          'presets': ['latest']
        }
      },
      // 处理模板文件
      {
        test: /\\.tpl$/,
        loader: 'ejs-loader'
      },
      // 处理 scss
      {
        test: /\\.scss$/,
        use: [
          // 提取css成单独文件(如果要内联到html,可以使用 style-loader)
          {
            loader: miniCssExtractPlugin.loader,
            options: {
              // 开发环境下,热更新
              hmr: process.env.NODE_ENV === 'development'
            }
          },
          'css-loader',
          {
            loader: 'postcss-loader',
            options: {
              plugins: function() {
                return [autoprefixer('last 5 versions')]
              }
            }
          },
          'sass-loader'
        ]
      },
      // 处理图片
      {
        test: /\\.(png|jpg|jpeg|gif|svg|ico)$/i,
        loader: [
          'url-loader?limit=1024&name=img/[name]-[hash:16].[ext]',
          'image-webpack-loader' // 压缩图片
        ]
      }
    ]
  },
  plugins: [
    new uglify(), // 压缩混淆js
    new HtmlWebpackPlugin({
      minify: {
        removeComments: true,
        collapseWhitespace: true
      },
      filename: 'index.html', // 把html最后放到 dist/index.html 中去
      template: path.resolve(__dirname, './src/index.html'),
      title: '新闻头条',
      // chunks 是 块儿 的意思,也就是js文件和文件夹的意思
      chunksSortMode: 'manual', // 按照下面 chunks 中数组顺序引入脚本文件
      chunks: ['index'], // 和 entry 的文件名匹配
      // 譬如 index.html 会引入 src/js/ 下的多个脚本文件,
      // 而脚本之间是有依赖顺序的,所以需要告诉webpack,让它按照我 chunks 数组的顺序来引入js文件
      excludeChunks: ['node_modules'],
      hash: true, // 文件名后缀带hash,缓存用
    }),
    new miniCssExtractPlugin({
      filename: 'css/[name].css', // 把最终提取的css文件放进 dist/css/ 文件夹下
    })
  ],
  devServer: {
    watchOptions: {
      ignored: /node_modules/
    },
    port: 3000,
    host: 'localhost',
  }
}

module.exports = config;

package.json

{
  "name": "webpack-config",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "webpack": "webpack",
    "dev": "webpack-dev-server"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "autoprefixer": "^9.5.1",
    "babel-core": "^6.26.3",
    "babel-loader": "^7.1.5",
    "babel-plugin-transform-runtime": "^6.23.0",
    "babel-preset-latest": "^6.24.1",
    "css-loader": "^2.1.1",
    "ejs": "^3.1.5",
    "ejs-loader": "^0.3.3",
    "file-loader": "^3.0.1",
    "html-webpack-plugin": "^3.2.0",
    "image-webpack-loader": "^4.6.0",
    "mini-css-extract-plugin": "^0.7.0",
    "node-sass": "^4.11.0",
    "postcss-loader": "^3.0.0",
    "sass-loader": "^7.1.0",
    "style-loader": "^0.23.1",
    "uglifyjs-webpack-plugin": "^2.1.2",
    "url-loader": "^1.1.2",
    "webpack": "^4.30.0",
    "webpack-cli": "^3.3.0",
    "webpack-dev-server": "^3.7.2"
  }
}

说明

package.json 命令说明

"scripts": {
  // 生产环境
  "webpack": "webpack --config webpack.config.js",
  // 开发环境
  // 用 webpack-dev-server 在 localhost:3000 下热更新;监听 dist 文件夹;用 webpack.config.js 文件的配置;要展示进度,打包的模块,彩色的,打包的具体信息
  "dev": "webpack-dev-server --host localhost --content-base dist/ --hot --config webpack.config.js --progress --display-modules --colors --display-reasons"
},

注意点

  1. 写的 scss 不会自动引入到 html 中去,需要在相应入口文件 js 中 import 引入
  2. dev 开发环境热更新时,scss 不会打包到 dist 目录下去,而是在内存中;所以得运行 npm run webpack 命令打包才会到 dist 目录中去