Webpack入门 二.资源管理

如果您从一开始就一直关注指南,那么现在您将看到一个显示“Hello webpack”的小项目。 现在让我们尝试合并一些其他资产,比如图像,看看如何处理它们。

在webpack之前,前端开发人员会使用grunt和gulp等工具来处理这些资产,并将它们从/ src文件夹移动到/ dist或/ build目录中。 同样的想法用于JavaScript模块,但像webpack这样的工具将动态捆绑所有依赖项(创建所谓的依赖图)。 这很好,因为现在每个模块都明确声明了它的依赖关系,我们将避免捆绑未使用的模块。

最酷的webpack功能之一是除了JavaScript之外,还可以包含任何其他类型的文件,其中有一个加载器。 这意味着上面列出的JavaScript相同的好处(例如显式依赖关系)可以应用于构建网站或Web应用程序所使用的所有内容。 让我们从CSS开始,因为您可能已经熟悉了该设置。

设置

在我们开始之前,让我们对项目进行一些小改动:
dist/index.html

  <!doctype html>
  <html>
    <head>
-    <title>Getting Started</title>
+    <title>Asset Management</title>
    </head>
    <body>
-     <script src="main.js"></script>
+     <script src="bundle.js"></script>
    </body>
  </html>

webpack.config.js

  const path = require('path');

  module.exports = {
    entry: './src/index.js',
    output: {
-     filename: 'main.js',
+     filename: 'bundle.js',
      path: path.resolve(__dirname, 'dist')
    }
  };

加载CSS

要从JavaScript模块中导入CSS文件,您需要在模块配置中安装并添加style-loader和css-loader:

npm install --save-dev style-loader css-loader

webpack.config.js

  const path = require('path');

  module.exports = {
    entry: './src/index.js',
    output: {
      filename: 'bundle.js',
      path: path.resolve(__dirname, 'dist')
    },
+   module: {
+     rules: [
+       {
+         test: /\.css$/,
+         use: [
+           'style-loader',
+           'css-loader'
+         ]
+       }
+     ]
+   }
  };

这使您可以将’./style.css’导入到依赖于该样式的文件中。 现在,当运行该模块时,带有字符串化css的<style>标记将插入到html文件的<head>中。

让我们通过向我们的项目添加一个新的style.css文件并将其导入我们的index.js来尝试:
project

  webpack-demo
  |- package.json
  |- webpack.config.js
  |- /dist
    |- bundle.js
    |- index.html
  |- /src
+   |- style.css
    |- index.js
  |- /node_modules

src/style.css

.hello {
  color: red;
}

src/index.js

  import _ from 'lodash';
+ import './style.css';

  function component() {
    const element = document.createElement('div');

    // Lodash, now imported by this script
    element.innerHTML = _.join(['Hello', 'webpack'], ' ');
+   element.classList.add('hello');

    return element;
  }

  document.body.appendChild(component());

现在运行您的构建命令:

npm run build

> webpack-demo@1.0.0 build /home/hb/Development/webpack-demo
> webpack

Hash: d9b8525928da168f90fd
Version: webpack 4.39.2
Time: 2691ms
Built at: 08/22/2019 2:37:27 PM
    Asset      Size  Chunks             Chunk Names
bundle.js  74.5 KiB       0  [emitted]  main
Entrypoint main = bundle.js
[1] ./src/index.js 280 bytes {0} [built]
[2] (webpack)/buildin/global.js 472 bytes {0} [built]
[3] (webpack)/buildin/module.js 497 bytes {0} [built]
[4] ./src/style.css 403 bytes {0} [built]
[5] ./node_modules/css-loader/dist/cjs.js!./src/style.css 166 bytes {0} [built]
    + 3 hidden modules

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/

再次在浏览器中打开index.html,您应该看到Hello webpack现在以红色设置。要查看webpack的作用,请检查页面(不要查看页面源,因为它不会显示结果,因为<style>标记是由 JavaScript动态创建的)并查看页面的head标记。它应该包含我们在index.js中导入的样式块。
请注意,您可以(在大多数情况下)最小化css,以便在生产中获得更好的加载时间。 最重要的是,加载器几乎存在于你能想到的任何CSS风格 - postcss,sass等等。

加载图片

所以现在我们正在使用我们的CSS,但是我们的图像如背景和图标呢? 使用文件加载器,我们也可以轻松地将它们合并到我们的系统中:

npm install --save-dev file-loader

webpack.config.js

  const path = require('path');

  module.exports = {
    entry: './src/index.js',
    output: {
      filename: 'bundle.js',
      path: path.resolve(__dirname, 'dist')
    },
    module: {
      rules: [
        {
          test: /\.css$/,
          use: [
            'style-loader',
            'css-loader'
          ]
        },
+       {
+         test: /\.(png|svg|jpg|gif)$/,
+         use: [
+           'file-loader'
+         ]
+       }
      ]
    }
  };

现在,当您从’./my-image.png’导入MyImage时,该图像将被处理并添加到您的输出目录中,并且MyImage变量将包含处理后该图像的最终URL。 当使用css-loader时,如上所示,CSS中的url(’。/ my-image.png’)将发生类似的过程。 加载程序将识别这是一个本地文件,并将’./my-image.png’路径替换为输出目录中图像的最终路径。 html-loader以相同的方式处理<img src =“./ my-image.png”/>。

让我们在项目中添加一个图像,看看它是如何工作的,你可以使用你喜欢的任何图像:
project

  webpack-demo
  |- package.json
  |- webpack.config.js
  |- /dist
    |- bundle.js
    |- index.html
  |- /src
+   |- icon.png
    |- style.css
    |- index.js
  |- /node_modules

src/index.js

  import _ from 'lodash';
  import './style.css';
+ import Icon from './icon.png';

  function component() {
    const element = document.createElement('div');

    // Lodash, now imported by this script
    element.innerHTML = _.join(['Hello', 'webpack'], ' ');
    element.classList.add('hello');

+   // Add the image to our existing div.
+   const myIcon = new Image();
+   myIcon.src = Icon;
+
+   element.appendChild(myIcon);

    return element;
  }

  document.body.appendChild(component());

src/style.css

  .hello {
    color: red;
+   background: url('./icon.png');
  }

让我们创建一个新的构建并再次打开index.html文件:

npm run build

...
                               Asset      Size  Chunks                    Chunk Names
da4574bb234ddc4bb47cbe1ca4b20303.png  3.01 MiB          [emitted]  [big]
                           bundle.js  76.7 KiB       0  [emitted]         main
Entrypoint main = bundle.js
...

如果一切顺利,您现在应该将您的图标视为重复背景,以及我们的Hello webpack文本旁边的img元素。 如果检查此元素,您将看到实际文件名已更改为5c999da72346a995e7e2718865d019c8.png。 这意味着webpack在src文件夹中找到了我们的文件并进行了处理!

加载字体

那么像字体这样的其他资产呢? 文件和URL加载器将获取您通过它们加载的任何文件,并将其输出到您的构建目录。 这意味着我们可以将它们用于任何类型的文件,包括字体。 让我们更新我们的webpack.config.js来处理字体文件:
webpack.config.js

  const path = require('path');

  module.exports = {
    entry: './src/index.js',
    output: {
      filename: 'bundle.js',
      path: path.resolve(__dirname, 'dist')
    },
    module: {
      rules: [
        {
          test: /\.css$/,
          use: [
            'style-loader',
            'css-loader'
          ]
        },
        {
          test: /\.(png|svg|jpg|gif)$/,
          use: [
            'file-loader'
          ]
        },
+       {
+         test: /\.(woff|woff2|eot|ttf|otf)$/,
+         use: [
+           'file-loader'
+         ]
+       }
      ]
    }
  };

将一些字体文件添加到项目中:
project

  webpack-demo
  |- package.json
  |- webpack.config.js
  |- /dist
    |- bundle.js
    |- index.html
  |- /src
+   |- my-font.woff
+   |- my-font.woff2
    |- icon.png
    |- style.css
    |- index.js
  |- /node_modules

配置加载程序并使用字体后,您可以通过@ font-face声明合并它们。 webpack将获取本地url(…)指令,就像使用图像一样:
src/style.css

+ @font-face {
+   font-family: 'MyFont';
+   src:  url('./my-font.woff2') format('woff2'),
+         url('./my-font.woff') format('woff');
+   font-weight: 600;
+   font-style: normal;
+ }

  .hello {
    color: red;
+   font-family: 'MyFont';
    background: url('./icon.png');
  }

现在运行一个新的构建,让我们看看webpack是否处理了我们的字体:

npm run build

...
                                 Asset      Size  Chunks                    Chunk Names
5439466351d432b73fdb518c6ae9654a.woff2  19.5 KiB          [emitted]
 387c65cc923ad19790469cfb5b7cb583.woff  23.4 KiB          [emitted]
  da4574bb234ddc4bb47cbe1ca4b20303.png  3.01 MiB          [emitted]  [big]
                             bundle.js    77 KiB       0  [emitted]         main
Entrypoint main = bundle.js
...

再次打开index.html,看看我们的Hello webpack文本是否已更改为新字体。 如果一切顺利,您应该看到更改。

加载数据

可以加载的另一个有用资产是数据,如JSON文件,CSV,TSV和XML。 对JSON的支持实际上是内置的,类似于NodeJS,这意味着默认情况下来自’./data.json’的导入数据将起作用。 要导入CSV,TSV和XML,您可以使用csv-loader和xml-loader。 让我们处理所有三个:

npm install --save-dev csv-loader xml-loader

webpack.config.js

  const path = require('path');

  module.exports = {
    entry: './src/index.js',
    output: {
      filename: 'bundle.js',
      path: path.resolve(__dirname, 'dist')
    },
    module: {
      rules: [
        {
          test: /\.css$/,
          use: [
            'style-loader',
            'css-loader'
          ]
        },
        {
          test: /\.(png|svg|jpg|gif)$/,
          use: [
            'file-loader'
          ]
        },
        {
          test: /\.(woff|woff2|eot|ttf|otf)$/,
          use: [
            'file-loader'
          ]
        },
+       {
+         test: /\.(csv|tsv)$/,
+         use: [
+           'csv-loader'
+         ]
+       },
+       {
+         test: /\.xml$/,
+         use: [
+           'xml-loader'
+         ]
+       }
      ]
    }
  };

将一些数据文件添加到项目中:
project

  webpack-demo
  |- package.json
  |- webpack.config.js
  |- /dist
    |- bundle.js
    |- index.html
  |- /src
+   |- data.xml
    |- my-font.woff
    |- my-font.woff2
    |- icon.png
    |- style.css
    |- index.js
  |- /node_modules

src/data.xml

<?xml version="1.0" encoding="UTF-8"?>
<note>
  <to>Mary</to>
  <from>John</from>
  <heading>Reminder</heading>
  <body>Call Cindy on Tuesday</body>
</note>

现在,您可以导入这四种类型的数据中的任何一种(JSON,CSV,TSV,XML),并且导入它的Data变量将包含已解析的JSON以便于使用:
src/index.js

  import _ from 'lodash';
  import './style.css';
  import Icon from './icon.png';
+ import Data from './data.xml';

  function component() {
    const element = document.createElement('div');

    // Lodash, now imported by this script
    element.innerHTML = _.join(['Hello', 'webpack'], ' ');
    element.classList.add('hello');

    // Add the image to our existing div.
    const myIcon = new Image();
    myIcon.src = Icon;

    element.appendChild(myIcon);

+   console.log(Data);

    return element;
  }

  document.body.appendChild(component());

重新运行npm run build命令并打开index.html。 如果您在开发人员工具中查看控制台,您应该能够看到导入的数据已记录到控制台!

全局资源

上面提到的所有内容中最酷的部分是以这种方式加载资源允许您以更直观的方式将模块和资源组合在一起。 您可以使用使用它们的代码对资产进行分组,而不是依赖包含所有内容的全局/资源目录。 例如,像这样的结构非常有用:

- |- /assets
+ |– /components
+ |  |– /my-component
+ |  |  |– index.jsx
+ |  |  |– index.css
+ |  |  |– icon.svg
+ |  |  |– img.png

这种设置使您的代码更加便携,因为现在紧密耦合的所有内容都存在。 假设你想在另一个项目中使用/ my-component,只需复制或移动到那里的/ components目录即可。 只要您安装了任何外部依赖项并且您的配置定义了相同的加载器,您就应该好了。
但是,假设您已陷入旧方式,或者您拥有多个组件(视图,模板,模块等)之间共享的资产。 仍然可以将这些资产存储在基本目录中,甚至可以使用别名来使它们更容易import

包起来

对于下一个指南,我们将不会使用我们在本指南中使用的所有不同资源,所以让我们做一些清理,以便我们为下一部分指南输出管理做好准备:
project

  webpack-demo
  |- package.json
  |- webpack.config.js
  |- /dist
    |- bundle.js
    |- index.html
  |- /src
-   |- data.xml
-   |- my-font.woff
-   |- my-font.woff2
-   |- icon.png
-   |- style.css
    |- index.js
  |- /node_modules

webpack.config.js

  const path = require('path');

  module.exports = {
    entry: './src/index.js',
    output: {
      filename: 'bundle.js',
      path: path.resolve(__dirname, 'dist')
    },
-   module: {
-     rules: [
-       {
-         test: /\.css$/,
-         use: [
-           'style-loader',
-           'css-loader'
-         ]
-       },
-       {
-         test: /\.(png|svg|jpg|gif)$/,
-         use: [
-           'file-loader'
-         ]
-       },
-       {
-         test: /\.(woff|woff2|eot|ttf|otf)$/,
-         use: [
-           'file-loader'
-         ]
-       },
-       {
-         test: /\.(csv|tsv)$/,
-         use: [
-           'csv-loader'
-         ]
-       },
-       {
-         test: /\.xml$/,
-         use: [
-           'xml-loader'
-         ]
-       }
-     ]
-   }
  };

src/index.js

  import _ from 'lodash';
- import './style.css';
- import Icon from './icon.png';
- import Data from './data.xml';
-
  function component() {
    const element = document.createElement('div');
-
-   // Lodash, now imported by this script
    element.innerHTML = _.join(['Hello', 'webpack'], ' ');
-   element.classList.add('hello');
-
-   // Add the image to our existing div.
-   const myIcon = new Image();
-   myIcon.src = Icon;
-
-   element.appendChild(myIcon);
-
-   console.log(Data);

    return element;
  }

  document.body.appendChild(component());
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值