webpack掠影-2

370 阅读5分钟

这是我参与8月更文挑战的第25天,活动详情查看:8月更文挑战

webpack 掠影-代码

前面我们已经学习了如何让 webpack 工作,包含开发时的 webpack-dev-server 和 用于生产环境的 webpack 打包输出文件。今天我们进一步了解 webpack。

一、 抽离 css 文件

前面我们通过配置 loader 使 webpack 可以处理 import some.css,但是我们发现 webpack 是把 css 变成 style 标签插入到 html 文件中;接着我们将通过 mini-css-extract-plugincss 抽离成单独的文件,并且通过 link 标签的形式引入到 html 文件中;

1.1 安装 mini-css-extract-plugin 插件

npm install mini-css-extract-plugin --dev

1.2 导入 mini-css-extract-plugin 插件,并修改配置文件;有两处修改:

  • 修改 modules 字段中处理 css 的 loader
  • 在 plugins 中增加一个 mini-css-extract-plugin 的实例
  • 配置对象 Object:
    • filename: 'main.css' 输出的 css 文件名字和路径,如果不含路径则直接输出到 output 对应的目录,如果包含目录,则会产出到对应目录
const path = require('path');

const HTMLWebpackPlugin = require('html-webpack-plugin');

+ const MiniCSSExtractPlugin = require('mini-css-extract-plugin'); // 抽离 css文件

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  devServer: {
    contentBase: './build', 
    port: 3000, 
    open: true,
    progress: true,
    proxy: { 
      '/api': {
        target: 'http://domain.com/somet/api',
        changeOrigin: true,
        secure: false
      }
    }
  },
  module: {
    rules: [
-      {
-        test: /.css$/,
-        use: ['style-loader', 'css-loader']
-      },
+      {
+        test: /.css$/,
+        use: [
+          MiniCSSExtractPlugin.loader,
+          'css-loader'
+        ]
+      }
    ]
  },
  plugins: [
    new HTMLWebpackPlugin({
      template: './src/index.html',
      hash: true, 
      filename: 'index.html', 
      minify: { 
        removeAttributeQuotes: true,
        collapseWhitespace: true 
      }
    }),
    // 抽离 css 文件
+    new MiniCSSExtractPlugin({
+      filename: 'main.css'
+    })
  ]
}

  • 效果

wbp2-extract-css.png

二、 处理 css 预处理器

日常开发中我们开会经常使用一些 css 预处理语言,如 less、sass、stylus 等,这里以 less 为例,展示 webpack 如何处理 css 预处理器。处理 CSS 预处理器,我们同样需要借助 loader 的力量;

2.1 安装对应的 loader

yarn add lessc less-loader -D

2.2 在 src 目录下增加 index.less 文件

body {
  background: #000;
  div {
    color: deepskyblue;
  }
}

2.3 在 index.js 中导入 index.less 文件

import './index.css';

+ import './index.less'

document.addEventListener('DOMContentLoaded', function () {
  let div = document.createElement('div');
  div.innerHTML = 'Hello World';
  document.body.appendChild(div);
  div = null;
});

2.4 修改 webpack 配置文件

const path = require('path');

const HTMLWebpackPlugin = require('html-webpack-plugin');
const MiniCSSExtractPlugin = require('mini-css-extract-plugin'); // 抽离 css文件

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  devServer: {
    contentBase: './build', 
    port: 3000, 
    open: true,
    progress: true, 
    proxy: { 
      '/api': { 
        target: 'http://domain.com/somet/api',
        changeOrigin: true,
        secure: false
      }
    }
  },
  module: {
    rules: [
      {
        test: /.css$/,
        use: [
          MiniCSSExtractPlugin.loader,
          'css-loader'
        ]
      },
+      {
+        test: /.less$/,
+        use: [
+          MiniCSSExtractPlugin.loader,
+          'css-loader',
+          'less-loader'
+        ]
+      }
    ]
  },
  plugins: [
    new HTMLWebpackPlugin({
      template: './src/index.html', 
      hash: true, 
      filename: 'index.html',
      minify: { 
        removeAttributeQuotes: true,
        collapseWhitespace: true 
      }
    }),
    // 抽离 css 文件
    new MiniCSSExtractPlugin({
      filename: 'main.css'
    })
  ]
}

  • 效果如图

wbp2-css-preprocesslang.png

三、css 属性自动增加前缀

日常开发过程中,我们经过需要给 CSS3 的属性增加前缀,例如 -webkit 等,这些工作也可以通过 webpack 帮我们完成;完成这个工作需要借助两个工具:postcss-loaderautoprefixerpostcss-loadercss 处理层 js 可以理解的内容,然后调用插件 autoprefixerautoprefixer 就是自动前缀的意思;

3.1 安装 postcss-loader、autoprefixer

yarn add postcss-loader、autoprefixer -D

3.2 修改 less 文件

body {
  background: #000;
  div {
+    transform: rotate(45deg);
    color: deepskyblue;
  }
}

3.3 在项目目录下增加 postcss 的配置文件:postcss.config.js

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

3.4 修改配置文件

const path = require('path');

const HTMLWebpackPlugin = require('html-webpack-plugin');
const MiniCSSExtractPlugin = require('mini-css-extract-plugin'); // 抽离 css文件

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  devServer: {
    // 开发服务器的配置
    contentBase: './build',  
    port: 3000,  
    open: true, 
    progress: true, 
    proxy: { 
      '/api': {  
        target: 'http://domain.com/somet/api',
        changeOrigin: true,
        secure: false
      }
    }
  },
  module: {
    rules: [
   
      {
        test: /.css$/,
        use: [
          MiniCSSExtractPlugin.loader,
          'css-loader'
        ]
      },
      {
        test: /.less$/,
        use: [
          MiniCSSExtractPlugin.loader,
          'css-loader',
+          'postcss-loader',
          'less-loader' // 先调用 less-loader,因为需要先将 less 处理成 css
        ]
      }
    ]
  },
  plugins: [
    new HTMLWebpackPlugin({
      template: './src/index.html', 
      hash: true, 
      filename: 'index.html', 
      minify: { 
        removeAttributeQuotes: true,
        collapseWhitespace: true 
      }
    }),
    // 抽离 css 文件
    new MiniCSSExtractPlugin({
      filename: 'css/main.css'
    })
  ]
}
  • 效果

wbp2-css-autoprefixer.png

四、 处理图片

4.1 处理 HTML 中的 img 图片

为什么要处理 HTML 文件中图片?还记得,我们使用 html-webpack-plugin 插件,把模板 HTML 文件从项目的源文件目录 src 复制到 输出目录中,开发时同样都是把图片放在 src 目录下,但是输出目录中没有对应图片,这就会导致 HTML 引入图片报错;

  • 安装 html-withimg-loader
yarn add html-withimg-loader -D
  • 安装 file-loader 和 url-loader

如果想完成页面中引入图片这个工作,还需要 file-loader 和 url-loader;但是我在写这些例子时,发现 file-loader 升级 5.x 后之前的配置(如下)会报错;所以本例的 file-loader 并没有采用最新版,而是采用的 url-loader 的 2.2.0 和 file-loader 的 4.2.0 版本,这些版本都是之前项目中稳定运行的版本;

module.exports = {
  modules: {
    rules: [
        {
           test: /.(jpeg|png|jpg)$/,
           use: {
             loader: 'url-loader',
             options: {
               limit: 200 * 1024, // 可以把设置小于某个值的图片或者文件打包成 base64,如果超过这个值自动输出为文件;
               outputPath: 'img/', // 图片输出到的目录
               publicPath: 'https://www.dahai.com/' // 给图片设置单独的 CDN 路径
             }
           }
         },
         {
           test: /.html$/,
           use: 'html-withimg-loader' // 处理 html 中的 img 引用的图片
         }
    ]
  }
}

所以,安装指定版本的 url-loader、file-loader

yarn ade url-loader@2.2.0 file-loader@4.2.0 -D

4.2 修改配置文件

const path = require('path');

const HTMLWebpackPlugin = require('html-webpack-plugin');
const MiniCSSExtractPlugin = require('mini-css-extract-plugin'); // 抽离 css文件

module.exports = {
  entry: './src/index.js',
  mode: 'production',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js'
  },
  devServer: {
    // 开发服务器的配置
    contentBase: './dist', // 静态资源文件目录
    port: 3000, // 开发服务器启动的端口
    open: true, // 是否自动启动浏览器
    progress: true, // 进度条
    proxy: { // 配置代理
      '/api': { // 将带有 /api 的请求,转发值 target 指向的域名
        target: 'http://domain.com/somet/api',
        changeOrigin: true,
        secure: false
      }
    }
  },
  module: {
    rules: [
      {
        test: /.css$/,
        use: [
          MiniCSSExtractPlugin.loader,
          'css-loader'
        ]
      },
      {
        test: /.less$/,
        use: [
          MiniCSSExtractPlugin.loader,
          'css-loader',
          'postcss-loader',
          'less-loader'
        ]
      },
+      {
+        test: /.(jpeg|png|jpg)$/,
+        use: {
+          loader: 'url-loader',
+          options: {
+            limit: 5 * 1024,
+            outputPath: '/img/'
+          }
+        }
+      },
+      {
+        test: /.(htm|html)$/,
+        use:  'html-withimg-loader' // 处理 html 中的 img 引用的图片
+      }
    ]
  },
  plugins: [
    new HTMLWebpackPlugin({
      template: './src/index.html', // 需要引入输出文件的 html 文件模板
      hash: true, // 给引入的 js 加hash
      filename: 'index.html', // 输出的 html 文件的名字(插件会把模板 html 复制到输出目录中)
      minify: { // 压缩优化输出的 html 文件配置
        removeAttributeQuotes: true, // 删除行内属性的双引号
        collapseWhitespace: true // 删除换行,使内容保持在一行
      }
    }),
    // 抽离 css 文件
    new MiniCSSExtractPlugin({
      filename: 'css/main.css'
    })
  ]
}

4.3 css/less 中使用图片

经过上面的配置后,同样支持在 CSS 文件中通过引用图片,同样会得到正确的处理;

body {
  background: #000;
  div {
    margin-top: 100px;
    display: inline-block;
    transform: rotate(45deg);
    color: deepskyblue;
  }

  p {
    width: 100px;
    height: 100px;
    background: url("./stars.jpeg") ;
    color: #fff;
  }
}
  • 效果如图

wbp2-process-img.png