zoukankan      html  css  js  c++  java
  • 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'],
              },
            },
          },
        ],
      },
    }
  • 相关阅读:
    如何统计一个字符串中某个字符出现的次数
    从GitHub克隆项目到本地
    nginx能做什么
    dubbo的使用实例
    zookeeper单机安装
    Http发送post(x-www-form-urlencoded)请求
    集群与分布式的区别
    cas的客户端应用是负载均衡,单点退出怎么办?
    mybatis执行DDL语句
    sql server 行列互换
  • 原文地址:https://www.cnblogs.com/moqiutao/p/12932657.html
Copyright © 2011-2022 走看看