webpack笔记-webpack基础用法(二)

webpack 本质上是一个打包工具,它会根据代码的内容解析模块依赖,帮助我们把多个模块的代码打包。

一切文件:JavaScript、CSS、SCSS、图片、模板,在 Webpack 眼中都是一个个模块,这样的好处是能清晰的描述出各个模块之间的依赖关系,以方便 Webpack 对模块进行组合和打包。 经过 Webpack 的处理,最终会输出浏览器能使用的静态资源。

 entry

webpack 构建的入口entry,webpack 会读取这个文件,并从它开始解析依赖,在内部构件一个依赖图,这个依赖图会引用项目中使用到的各个模块,然后进行打包,生成一个或者多个 bundle 文件。

我们常见的项目中,如果是单页面应用,那么入口只有一个;如果是多个页面的项目,那么通常是一个页面会对应一个构建入口。

单⼊⼝:entry 是⼀个字符串,如下代码:

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

上述代码等价于:

// 上述配置等同于
module.exports = {
  entry: {
    main: './src/index.js'
  }
}

多⼊口:entry 是⼀个对象,如下代码:

module.exports = {
  entry: {
    app: './src/app.js',
    home: './src/home.js'
  }
};

还有一种场景比较少用到,即是多个文件作为一个入口来配置,webpack 会解析多个文件的依赖然后打包到一起:

// 使用数组来对多个文件进行打包
module.exports = {
  entry: {
    main: [
      './src/foo.js',
      './src/bar.js'
    ]
  }
}

动态 entry

const path = require('path');
const fs = require('fs');

// src/pages 目录为页面入口的根目录
const pagesRoot = path.resolve(__dirname, './src/pages');
// fs 读取 pages 下的所有文件夹来作为入口,使用 entries 对象记录下来
const entries = fs.readdirSync(pagesRoot).reduce((entries, page) => {
  // 文件夹名称作为入口名称,值为对应的路径,可以省略 `index.js`,webpack 默认会寻找目录下的 index.js 文件
  entries[page] = path.resolve(pagesRoot, page);
  return entries;
}, {});

module.exports = {
  // 将 entries 对象作为入口配置
  entry: entries,

  // ...
};

output

output用来告诉 webpack 如何将编译后的文件输出到磁盘。webpack 构建生成的文件名、路径等都是可以配置的,在配置文件中使用 output 字段来进行设置:

module.exports = {
  // ...
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'bundle.js',
  },
}

// 或者使用 entry 的名称
module.exports = {
  entry: {
    main: './src/index.js' // main 为 entry 的名称
  },
  output: {
    filename: '[name].js', // 使用 [name] 来引用 entry 名称,在这里即为 main
    path: path.join(__dirname, '/dist/[hash]'),
    // 路径中使用 hash,每次构建时会有一个不同 hash 值,可以用于避免发布新版本时浏览器缓存导致代码没有更新
    // 文件名中也可以使用 hash
  },
}

 loader

我们在前端构建中会遇见需要使用各式各样的文件,例如 css 代码,图片,模板代码等。webpack 中提供一种处理多种文件格式的机制,便是使用 loader。我们可以把 loader 理解为是一个转换器,负责把某种文件格式的内容转换成 webpack 可以支持打包的模块。例如我们需要 css-loader 来处理 .css 文件(这里其实还需要 style-loader),最终把不同格式的文件都解析成 js 代码,以便打包后在浏览器中运行。

webpack 开箱即用只支持 JS 和 JSON 两种文件类型,通过 Loaders 去支持其它文件类型并且把它们转化成有效的模块,并且可以添加到依赖图中。

本身是一个函数,接受源文件作为参数,返回转换的结果。

 常见的 Loaders 有哪些?

  •  babel-loader:转换ES6、ES7等JS新特性语法
  • css-loader:支持.css文件的加载和解析
  • less-loader:将less文件转换成css
  • ts-loader:将TS转换成JS
  • file-loader:进行图片、字体等的打包
  • raw-loader:将文件以字符串的形式导入
  • thread-loader:多线程打包JS和CSS

下面我们来配置下处理css的loader以及ES6转ES5的loader,首先npm安装如下loader,

  • css-loader:npm i style-loader css-loader -D
  • babel-loader:npm install babel-loader @babel/core @babel/preset-env

rules的配置如下:

module: {
        rules:[
            {
                test: /.css$/,
                use: ['style-loader','css-loader']
            },
            {
                test: /.js$/,  // 匹配文件路径的正则表达式,通常我们都是匹配文件类型后缀
                exclude: /node_modules/, // 排除掉node_modules这个文件夹的js文件
                include: [
                    path.resolve(__dirname,'src') // 指定哪些路径下的文件需要经过 loader 处理
                ],
                use: { // 指定使用的 loader
                    loader: 'babel-loader', // babel-loader 可以使用 babel 来将 ES6 代码转译为浏览器可以执行的的 ES5 代码
                    options: {
                        presets: ['@babel/preset-env']
                    }
                }
            }
        ]
    }

 plugin

plugin 在 webpack 中的配置只是把实例添加到 plugins 字段的数组中。不过由于需要提供不同的功能,不同的 plugin 本身的配置比较多样化。

常用的plugin:

  • CommonsChunkPlugin:将chunks相同的模块代码提取成公共js,webpack4.x版本使用optimization.SplitChunks
  • cleanWebpackPlugin:清理构建目录
  • ExtractTextWebpackPlugin:将CSS从bundle文件里提取成一个独立的CSS文件(webpack3.x版本),webpack4.x版本使用mini-css-extract-plugin
  • CopyWebpackPlugin:将文件或者文件夹拷贝到构建的输出目录
  • HtmlWebpackPlugin:创建html文件去承载输出的bundle
  • UglifyjsWebpackPlugin:压缩JS
  • ZipWebpackPlugin:将打包出的资源生成一个zip包
const path = require('path');
module.exports = {
    output: {
        filename: 'bundle.js'
    },
    plugins: [
        new HtmlWebpackPlugin({   // 放到plugins数组里
            template: './src/index.html'
        })
    ]
};

在 webpack 的构建流程中,plugin 用于处理更多其他的一些构建任务。可以这么理解,模块代码转换的工作由 loader 来处理,除此之外的其他任何工作都可以交由 plugin 来完成。

例如,使用 copy-webpack-plugin 来复制其他不需要 loader 处理的文件,只需在配置中通过 plugins 字段添加新的 plugin 即可:

npm install copy-webpack-plugin -D 
# 插件通常为第三方的 npm package,都需要安装后才能使用
const CopyPlugin = require('copy-webpack-plugin');

module.exports = {
  // ...

  plugins: [
    new CopyPlugin([
      { from: 'src/public', to: 'public' },
    ]),
  ],
};

mode

mode,构建模式是 webpack v4 引入的新概念,用于方便快捷地指定一些常用的默认优化配置,mode 可以是 development,production,none 其中的一个,我们之前已经在配置文件中添加了相应的配置:

module.exports = {
  mode: 'development', // 指定构建模式为 development
  // ...
}

顾名思义,development 模式用于开发时使用,production 模式用于线上生产时使用,none 则是不需要任何默认优化配置时使用。

development 和 production 模式的区别:

  • 这两个模式会使用 DefinePlugin 来将 process.env.NODE_ENV 的值分别设置为 development 和 production,方便开发者在项目业务代码中判断当前构建模式。
  • production 模式会启用 TerserPlugin来压缩JS代码,让生成的代码文件更小。
  • development 模式会启用 devtools: 'eval' 配置,提升构建和再构建的速度。

前端构建基础配置

关联HTML

怎样将HTML引用路径和我们的构建结果关联起来,这个时候我们可以使用 html-webpack-plugin。

html-webpack-plugin 是一个独立的 package,在使用之前我们需要先安装它:

npm install html-webpack-plugin -D 

然后在 webpack 配置中,将 html-webpack-plugin 添加到 plugins 列表中:

const HtmlWebpackPlugin = require('html-webpack-plugin')

module.exports = {
  // ...
  plugins: [
    new HtmlWebpackPlugin({
      template: 'src/index.html', // 配置文件模板
    }),
  ],
}

这样,通过 html-webpack-plugin 就可以将我们的页面和构建 JS 关联起来,回归日常,从页面开始开发。如果需要添加多个页面关联,那么实例化多个 html-webpack-plugin, 并将它们都放到 plugins 字段数组中就可以了。

构建 CSS

我们编写 CSS,并且希望使用 webpack 来进行构建,为此,需要在配置中引入 loader 来解析和处理 CSS 文件:

module.exports = {
  module: {
    rules: {
      // ...
      {
        test: /.css/,
        include: [
          path.resolve(__dirname, 'src'),
        ],
        use: [
          'style-loader',
          'css-loader',
        ],
      },
    },
  }
}

上面配置的两个loader的作用:

  • css-loader 负责解析 CSS 代码,主要是为了处理 CSS 中的依赖,例如 @import 和 url() 等引用外部文件的声明;
  • style-loader 会将 css-loader 解析的结果转变成 JS 代码,运行时动态插入 style 标签来让 CSS 代码生效。

如果需要单独把 CSS 文件分离出来,我们需要使用 mini-css-extract-plugin 插件。

v4 版本之后才开始使用 mini-css-extract-plugin,之前的版本是使用 extract-text-webpack-plugin。

如下例子:

const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /.css/i,
        use: [
          // 因为这个插件需要干涉模块转换的内容,所以需要使用它对应的 loader
          MiniCssExtractPlugin.loader,
          'css-loader',
        ],
      },
    ],
  },

  plugins: [
    new MiniCssExtractPlugin({
      filename: '[name].css' // 这里也可以使用 [hash]
    }), // 将 css 文件单独抽离的 plugin
  ]
};

在上述使用 CSS 的基础上,通常我们会使用 Less/Sass 等 CSS 预处理器,webpack 可以通过添加对应的 loader 来支持,以使用 Less 为例

less-loader 只是 webpack 的转换器,启动 Less 你还需要安装 less 自身,同样地,sass-loader 也是这般。

在 webpack 配置中,添加一个配置来支持解析后缀为 .less 的文件:

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /.(less|css)$/,
        use: [
          // 因为这个插件需要干涉模块转换的内容,所以需要使用它对应的 loader
          MiniCssExtractPlugin.loader,
          'css-loader',
          'less-loader',
        ],
      },
    ],
  },
  // ...
}

处理图片文件

在前端项目的样式中总会使用到图片,虽然我们已经提到 css-loader 会解析样式中用 url() 引用的文件路径,但是图片对应的 jpg/png/gif 等文件格式,webpack 处理不了。是的,我们只要添加一个处理图片的 loader 配置就可以了,现有的 file-loader 就是个不错的选择。

file-loader 可以用于处理很多类型的文件,它的主要作用是直接输出文件,把构建后的文件路径返回。配置很简单,在 rules中添加一个字段,增加图片类型文件的解析配置:

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /.(png|jpg|gif)$/,
        use: [
          {
            loader: 'file-loader',
            options: {},
          },
        ],
      },
    ],
  },
}

使用babel

Babel 是一个让我们能够使用 ES 新特性的 JS 编译工具,我们可以在 webpack 中配置 Babel,以便使用 ES6、ES7 标准来编写 JS 代码。

module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /.jsx?/, // 支持 js 和 jsx 文件,使用 react 时需要
        include: [
          path.resolve(__dirname, 'src'), // 指定哪些路径下的文件需要经过 loader 处理
        ],
        use: {
          loader: 'babel-loader', // 指定使用的 loader
          options: {
            presets: ['@babel/preset-env'],
          },
        },
      },
    ],
  },
}
原文地址:https://www.cnblogs.com/moqiutao/p/12932657.html