Skip to content

Instantly share code, notes, and snippets.

@TorvaldsDB
Last active June 28, 2021 05:42
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save TorvaldsDB/62a57232d0c85a690f0660a7e6c170e3 to your computer and use it in GitHub Desktop.
Save TorvaldsDB/62a57232d0c85a690f0660a7e6c170e3 to your computer and use it in GitHub Desktop.
Webpack Basic Configuration

Webpack

Webpack 配置文件放置在webpack.config.js中,

代码源码在 src/, 文件分布结构图(使用tree ./

├── src
│   ├── css
│   │   ├── iconfont.css
│   │   └── index.less
│   ├── imgs
│   │   ├── angular.png
│   │   ├── doge.gif
│   │   ├── react.png
│   │   ├── vue.png
│   │   └── webpack.png
│   ├── index.html
│   ├── js
│   │   └── index.js
│   └── media
│       └── iconfont.ttf
└── webpack.config.js

Webpack 配置五大要素

// resolve 用来拼接绝对路径的方法
const { resolve } = require('path')
module.export = {
  // webpack 配置
  // 入口起点
  entry: './src/js/index.js',
  // 输出
  output: {
    // 输出文件名
    filename: 'built.js',
    // 输出路径
    // __dirname nodejs的变量, 代表当前文件的目录的绝对路径
    path: resolve(__dirname, 'build'),
  },
  // loader 的配置
  module: {
    rules: [
      // 详细loader配置
    ],
  },
  // plugins的配置
  plugins: [],
  // 模式
  mode: 'development',
}

把源码资源src打包到build/文件夹下

Webpack 主要工作:

1. 编译资源(浏览器可读)
2. 压缩代码(提高加载速度)
3. 打包后资源分类(方便管理)
4. 兼容性(一次编码, 多平台互用)

处理的文件主要包括: HTML, Javascript(ES6 -> ES5), CSS(SCSS, LESS), Image(.jpg, .png, .gif), Font

bundle(打包):

  1. 处理style(CSS)
    • loader: -style-loader- 创建style标签, 将JS中的样式资源插入到行中, 添加到head中生效. 我们需要把CSS与JS分离开, 所以这个loader不会再使用了
    • loader: ::css-loader::把CSS文件编译成CommonJS模块, 加载到JS中, 里面的内容是 样式字符串
    • loader: ::less-loader::把LESS文件编译成CSS文件
    • loader: ::postcss-loader::兼容性处理
      1. 还需要安装plugin postcss-preset-env
      2. postcss默认环境是在production. 在development, 我们需要声明node的development环境process.env.NODE_ENV = ‘development’
      3. postcss-preset-env 帮助postcss找到package.json中 ::browserlist::里面的配置, 通过配置加载指定的css兼容性样式
"browserslist": {
// 开发环境 --> 设置node环境变量: process.env.NODE_ENV = 'development'
"development": [
  "last 1 chrome version",
  "last 1 firefox version",
  "last 1 safari version"
],
// 生产环境: 默认是生产环境
"production": [
  ">0.2%",
  "not dead",
  "not op_mini all"
]
}

Postcss-loader 的配置:

{
loader: 'postcss-loader',
options: {
  ident: 'postcss',
  plugins: () => [
    // postcss的插件
    require('postcss-preset-env')(),
  ],
},
}
* _plugin_: ::mini-css-extract-plugin::从`css-loader`编译后的JS中提取CSS样式字符串到指定的`filename`文件中
plugins: [
  new MiniCssExtractPlugin({
  // 对输出的css重命名
  filename: 'css/built.css',
})
]
* _plugin_: ::optimize-css-assets-webpack-plugin::优化CSS资源(压缩CSS资源)
  1. 处理Image
    • CSS中的图片(如: background-image: url(image_path))
      • 只需要用file-loader就可以处理这类图片
      • ::url-loader::其实内部依赖file-loader, url-loader是为了可以对小图片进行base64处理
    • HTML中::::中的图片
      • ::html-loader::负责引入img, 从而能被url-loader进行处理. html-loader 并没有处理img 标签中的图片, 它只负责引入img, 处理还是用url-loader来处理的 注意: url-loader默认使用的是::ES6模块化::解析, 而html-loader引入图片是::CommonJS::, html-loader引入图片后, 如果直接用url-loader解析, 会出现图片引入为_[Object Module]_的问题. 解决: 在url-loader设置中, 关闭 url-loader 的 ES6 模块化, 使用 CommonJS 解析: esModule: false
  2. 打包HTML资源 plugin: ::html-webpack-plugin::
    • 配置template指定模板
    • 压缩HTML资源
      • ::html-webpack-plugin::配置minify, 可以直接压缩HTML代码
        • collapseWhitespace: true移除空格
        • removeComments: true移除注释
new HTMLWebpackPlugin({ 
template: './src/index.html',
minify: {
collapseWhitespace: true,
removeComments: true
}
})
  1. 打包其他资源(font)
    • loader: ::file-loader::需要配置exclude排除其他已经处理的文件类型
{
exclude: /\.(html|js|css|less|scss|png|jpg|gif)$/,
loader: 'file-loader',
options: {
name: '[hash:10].[name].[ext]'
}
}
  1. 处理Javascript Webpack 天生可以处理 JS/JSON 资源, 但只是处理简单的 JS(ES5). 对于JS 语法检查, JS 兼容性, JS 压缩(通过mode可以解决) 这些方面,我们还需要利用 Webpack的loader, plugins 来处理
    • JS 压缩
      • mode: ‘production’的时候, 可以自动压缩.
    • JS 语法检查: eslint-loader 配合使用airbnbJS语法规范, 需要在package.json中配置eslintConfig
"eslintConfig": {
	"extends": "airbnb-base"
}

webpack.config.js配置

{
    test: /\.js$/,
    loader: 'eslint-loader',
    exclude: /node_modules/,
    options: {
      // 自动修复eslint的错误
      fix: true,
    },
  }
* JS兼容性: `babel-loader`配合 `@babel/preset-env` `@babel/core`以及**按需加载**的`core-js`
	1. 基本js兼容性处理 : `@babel/preset-env`
	问题: 只能转换基本语法(处理ES6箭头函数), 对于 `promise` `proxy`高级用法无法转换
	2. 高级用法可以借助 `core-js`来转换
{
    test: /\.js$/,
    exclude: /node_modules/,
    loader: 'babel-loader',
    options: {
      // 预设: 指示babel做怎么样的兼容性处理
      // presets: ['@babel/preset-env'],
      presets: [
        [
          '@babel/preset-env',
          {
            // 按需加载
            useBuiltIns: 'usage',
            // 指定core-js版本
            corejs: {
              version: 3,
            },
            // 指定兼容性做到哪个版本浏览器
            targets: {
              chrome: '60',
              firefox: '60',
              ie: '9',
              safari: '10',
              edge: '17',
            },
          },
        ],
      ],
    },
  },

注意事项:

* `use` 数组中的loader遵循::FILO::(First In Last Out)调用顺序: ::从右到左::, 比如:
`use: [‘style-loader’, ‘css-loader’, ‘less-loader’]`是先调用 `less-loader` 再调用`css-loader`, 最后调用`style-loader`
* Image 有两种形式
	1. CSS中使用的图片(background-image)
		* 其实只使用`file-loader` 就可以处理了
		* 选用`url-loader`只是为了对小图片进行`base64`编码
	3. HTML 中使用的图片(img tab)
		* `html-loader`用来处理HTML中`img`资源
		* 注意: `html-loader`名字很奇怪, 他并不是处理整体HTML的, 只是处理HTML中的`img`资源的
	3. `html-loader`采用的是`CommonJS`模块化, `url-loader`采用的是`ES6 module`模块化, 当使用`html-loader`的时候, 需要将`url-loader`中的`ES6 module`禁用掉`esModule: false`, 否则HTML中的图片不会正常被编译, 出现`[object, module]`的问题.

综合以上, 可以进行下面配置:

const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const { resolve } = require('path');

// 定义nodejs环境变量: 决定使用browserslist的哪个环境
process.env.NODE_ENV = 'production';

// 复用loader
const commonCssLoader = [
  MiniCssExtractPlugin.loader,
  'css-loader',
  {
    loader: 'postcss-loader',
    // 还需要在package.json中定义 browserslist
    options: {
      ident: 'postcss',
      plugins: () => [require('postcss-preset-env')()],
    },
  },
];

module.exports = {
  entry: './src/js/index.js',
  output: {
    filename: 'js/built.js',
    path: resolve(__dirname, 'build'),
  },
  module: {
    rules: [
      {
        test: /\.css$/,
        use: commonCssLoader,
      },
      {
        test: /\.less$/,
        use: [...commonCssLoader, 'less-loader'],
      },
      /*
        正常来讲, 一个文件只能被一个loader处理.
        当一个文件要被多个loader处理的时候, 那么一定要指定loader执行的先后顺序
          限制性eslint, 再执行babel
      */
      {
        // 在package.json中eslintConfig --> airbnb
        test: /\.js$/,
        exclude: /node_modules/,
        // 优先执行
        enforce: 'pre',
        loader: 'eslint-loader',
        options: {
          fix: true,
        },
      },
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
        options: [
          '@babel/preset-env',
          {
            useBuiltIns: 'usage',
            corejs: { version: 3 },
            targets: {
              chrome: '60',
              firefox: 60,
            },
          },
        ],
      },
      {
        test: /\.(jpg|png|gif)/,
        loader: 'url-loader',
        options: {
          limit: 8 * 1024,
          name: '[hash:10].[name].[ext]',
          outputPath: 'imgs',
          esModule: false,
        },
      },
      {
        test: /\.html$/,
        loader: 'html-loader',
      },
      {
        exclude: /\.(js|css|less|html|jpg|png|gif)/,
        loader: 'file-loader',
        options: {
          outputPath: 'media',
        },
      },
    ],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        collapseWhitespace: true,
        removeComments: true,
      },
    }),
    new MiniCssExtractPlugin({
      filename: 'css/built.css',
    }),
    new OptimizeCssAssetsPlugin(),
  ],
  mode: 'production',
};

打包后得到这样的文件目录:

├── build
│   ├── imgs
│   │   ├── 077f2a8a3d.doge.gif
│   │   └── 55e1991eae.react.png
│   ├── index.html
│   ├── js
│   │   └── built.js
│   └── media
│       └── fc2b0de87e.iconfont.ttf
├── src
│   ├── css
│   │   ├── iconfont.css
│   │   └── index.less
│   ├── imgs
│   │   ├── angular.png
│   │   ├── doge.gif
│   │   ├── react.png
│   │   ├── vue.png
│   │   └── webpack.png
│   ├── index.html
│   ├── js
│   │   └── index.js
│   └── media
│       └── iconfont.ttf
└── webpack.config.js

#webpack#

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment