If you've been following the guides from the start, you will now have a small project that shows "Hello webpack". Now let's try to incorporate some other assets, like images, to see how they can be handled.css
若是你一直跟着咱们的Guide来操做,你如今应该有一个叫"Hello webpack"的项目了。如今,让咱们试着把它和其余资源合并在一块儿,就好比图片一类的东西。html
Prior to webpack, front-end developers would use tools like grunt and gulp to process these assets and move them from their /src folder into their /dist or /build directory. The same idea was used for JavaScript modules, but tools like webpack will dynamically bundle all dependencies (creating what's known as a dependency graph). This is great because every module now explicitly states its dependencies and we'll avoid bundling modules that aren't in use.前端
在webpack问世以前,前端的开发者们都是用grunt
啊,gulp
这样的工具来处理和移动资源,他们将资源从他们的/src
目录移动到/dist
或者/build
目录。JavaScript
模块使用了相同的想法,可是像webpack这样的工具会动态地捆绑全部的依赖关系(建立所谓的依赖关系图)这很好,由于如今每一个模块都明确地声明了它的依赖关系,咱们将避免捆绑未使用的模块。node
One of the coolest webpack features is that you can also include any other type of file, besides JavaScript, for which there is a loader. This means that the same benefits listed above for JavaScript (e.g. explicit dependencies) can be applied to everything used in building a website or web app. Let's start with CSS, as you may already be familiar with that setup.webpack
你知道webpack最酷的事情之一是什么吗?他不只能打包JS,还能够打包任何其它类型的文件,只要你设定好了加载器。这意味着,上面列出的对于打包JavaScript的好处(例如明确的依赖关系)也能够应用于构建网站或Web应用程序的全部内容。让咱们从CSS开始,由于您可能已经熟悉了这个设置。web
Let's make a minor change to our project before we get started:ajax
在咱们开始以前,让咱们给咱们的项目作一个微小的改变吧!(* ̄︶ ̄)正则表达式
<html> <head> - <title>Getting Started</title> + <title>Asset Management</title> </head> <body> <script src="./bundle.js"></script> </body> </html>
P.S.:这里再解释一次,代码行左边的+和-表示相比于原来的文件,增长了哪一行,减小了哪一行。express
In order to import a CSS file from within a JavaScript module, you need to install and add the style-loader and css-loader to your module configuration:npm
为了让JavaScript
模块能够获取CSS
文件,须要安装style-loader
和css-loader
,并添加它们到您的module
配置中:
npm install --save-dev style-loader css-loader
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' + ] + } + ] + } };
P.S.:这里我想为基础薄弱的朋友们解释一下test: /\.css$/
,这个是在写正则表达式呢,它的意思是“以.css结尾”若是你想大体了解一下这个东西而不是很深刻地去研究,我推荐菜鸟教程-正则表达式。
webpack uses a regular expression to determine which files it should look for and serve to a specific loader. In this case any file that ends with .css will be served to the style-loader and the css-loader.
webpack使用正则表达式来肯定应该查找哪些文件并将其提供给特定的加载程序。在这种状况下,任何以文件结尾的文件.css
将被提供给style-loader
和css-loader
。
This enables you to import './style.css' into the file that depends on that styling. Now, when that module is run, a <style> tag with the stringified css will be inserted into the <head> of your html file.
这使您可以import './style.css'
进入依赖于该样式的文件。如今,当这个模块运行时,<style>
带有字符串化CSS
的标签将被插入到<head>
你的html
文件中。
Let's try it out by adding a new style.css file to our project and import it in our index.js:
让咱们经过添加一个新的style.css
文件到咱们的项目中,并将其导入到咱们项目中的index.js
:
webpack-demo |- package.json |- webpack.config.js |- /dist |- bundle.js |- index.html |- /src + |- style.css |- index.js |- /node_modules
.hello { color: red; }
import _ from 'lodash'; + import './style.css'; function component() { var 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());
Now run your build command:
来吧,执行编译命令:
npm run build
输出结果:
Hash: 9a3abfc96300ef87880f Version: webpack 2.6.1 Time: 834ms Asset Size Chunks Chunk Names bundle.js 560 kB 0 [emitted] [big] main [0] ./~/lodash/lodash.js 540 kB {0} [built] [1] ./src/style.css 1 kB {0} [built] [2] ./~/css-loader!./src/style.css 191 bytes {0} [built] [3] ./~/css-loader/lib/css-base.js 2.26 kB {0} [built] [4] ./~/style-loader/lib/addStyles.js 8.7 kB {0} [built] [5] ./~/style-loader/lib/urls.js 3.01 kB {0} [built] [6] (webpack)/buildin/global.js 509 bytes {0} [built] [7] (webpack)/buildin/module.js 517 bytes {0} [built] [8] ./src/index.js 351 bytes {0} [built]
Open up index.html in your browser again and you should see that Hello webpack is now styled in red. To see what webpack did, inspect the page (don't view the page source, as it won't show you the result) and look at the page's head tags. It should contain our style block that we imported in index.js.
在你的浏览器中再一次打开index.html
吧,而后你应该能看见"Hello webpack"如今已经变成红色的了。若是你想知道webpack都干了些啥,实现了这种效果,请监听这个页面的加载吧,看一看页面的头部标签都写了些啥。确定包含了咱们的样式块在咱们导入进index.js
的时候。
Note that you can also split your CSS for better load times in production. On top of that, loaders exist for pretty much any flavor of CSS you can think of -- postcss, sass, and less to name a few.
注意,你还能够拆分您的CSS
文件以得到更好的加载时间。最重要的是,不管你对于CSS
的口味有多刁,都存在相应的加载器——就像postcss
、sass
,还有其它几种,都能加载的。
So now we're pulling in our CSS, but what about our images like backgrounds and icons? Using the file-loader we can easily incorporate those in our system as well:
那么好,如今咱们正在搞CSS,可是,对于我们的图片,就像那种,背景图片啊,图标啊,这个咋整呢?使用文件加载器,咱们能够很轻松地将它们也加入咱们的系统之中:
npm install --save-dev file-loader
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' + ] + } ] } };
Now, when you import MyImage from './my-image.png', that image will be processed and added to your output directory and the MyImage variable will contain the final url of that image after processing. When using the css-loader, as shown above, a similar process will occur for url('./my-image.png') within your CSS. The loader will recognize this is a local file, and replace the './my-image.png' path with the final path to the image in your output directory. The html-loader handles <img src="./my-image.png" /> in the same manner.
如今,当你须要从./my-image.png
导入MyImage
,那张图片将会被处理而后添加到你的输出目录中,而且MyImage
变量将会包含一个该图片处理后的url常量。当咱们使用CSS加载器的时候,好比把./my-image.png
打包到你的CSS文件里,就像上面展示出来的那样,是一个跟上面图片加载差很少的过程。加载器会发现这是一个本地文件,而后把./my-image.png
路径替换为output
目录中映像的最终路径。HTML加载器也会相同的方式来处理<img src="./my-image.png" />
P.S.:这里说一个小知识点,URL不是URI,这是两个抽象概念,不少人混为一谈。URL指的是统一资源定位符,而URI指的是统一资源标识符。URL是URI的子集。
Let's add an image to our project and see how this works, you can use any image you like:
让咱们给咱们的项目添加一张图片,而后看看这是怎么工做的吧,你可使用任意一张你喜欢的图片哦。
webpack-demo |- package.json |- webpack.config.js |- /dist |- bundle.js |- index.html |- /src + |- icon.png |- style.css |- index.js |- /node_modules
import _ from 'lodash'; import './style.css'; + import Icon from './icon.png'; function component() { var 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. + var myIcon = new Image(); + myIcon.src = Icon; + + element.appendChild(myIcon); return element; } document.body.appendChild(component());
.hello { color: red; + background: url('./icon.png'); }
Let's create a new build and open up the index.html file again:
让咱们再一次编译项目,而后打开index.html
:
npm run build
Hash: 854865050ea3c1c7f237 Version: webpack 2.6.1 Time: 895ms Asset Size Chunks Chunk Names 5c999da72346a995e7e2718865d019c8.png 11.3 kB [emitted] bundle.js 561 kB 0 [emitted] [big] main [0] ./src/icon.png 82 bytes {0} [built] [1] ./~/lodash/lodash.js 540 kB {0} [built] [2] ./src/style.css 1 kB {0} [built] [3] ./~/css-loader!./src/style.css 242 bytes {0} [built] [4] ./~/css-loader/lib/css-base.js 2.26 kB {0} [built] [5] ./~/style-loader/lib/addStyles.js 8.7 kB {0} [built] [6] ./~/style-loader/lib/urls.js 3.01 kB {0} [built] [7] (webpack)/buildin/global.js 509 bytes {0} [built] [8] (webpack)/buildin/module.js 517 bytes {0} [built] [9] ./src/index.js 503 bytes {0} [built]
If all went well, you should now see your icon as a repeating background, as well as an img element beside our Hello webpack text. If you inspect this element, you'll see that the actual filename has changed to something like 5c999da72346a995e7e2718865d019c8.png. This means webpack found our file in the src folder and processed it!
若是一切顺利,你如今应该看到你的图标铺满了背景,并且一个图片元素就在你的文本“Hello webpack”的一边。若是你监听了这个元素,你将会看到真实的图片名称已经被更换了,更换成相似于5c999da72346a995e7e2718865d019c8.png
的名字。这就意味着,webpack已经在src
目录下找到了咱们的文件并且处理了它。
So what about other assets like fonts? The file and url loaders will take any file you load through them and output it to your build directory. This means we can use them for any kind of file, including fonts. Let's update our webpack.config.js to handle font files:
那么,其它的资源呢?就好比说字体?文件加载器和url加载器将会处理任何你想处理的文件并输出它们到你的编译路径。这就意味着咱们可使用它们来处理各类各样的文件,固然包含字体文件。让咱们升级一下咱们的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' + ] + } ] } };
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
With the loader configured and fonts in place, you can use incorporate them via an @font-face declaration. The local url(...) directive will be picked up by webpack just as it was with the image:
就在加载器配置和字体的地方,你合并他们经过使用@font-face
注解。本地url(...)
指令将被webpack拾取,就像它与图像同样:
+ @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'); }
Now run a new build and let's see if webpack handled our fonts:
如今,让咱们运行一个新的编译,来看看咱们的webpack是如何处理咱们的字体的:
npm run build
Hash: b4aef94169088c79ed1c Version: webpack 2.6.1 Time: 775ms Asset Size Chunks Chunk Names 5c999da72346a995e7e2718865d019c8.png 11.3 kB [emitted] 11aebbbd407bcc3ab1e914ca0238d24d.woff 221 kB [emitted] bundle.js 561 kB 0 [emitted] [big] main [0] ./src/icon.png 82 bytes {0} [built] [1] ./~/lodash/lodash.js 540 kB {0} [built] [2] ./src/style.css 1 kB {0} [built] [3] ./~/css-loader!./src/style.css 420 bytes {0} [built] [4] ./~/css-loader/lib/css-base.js 2.26 kB {0} [built] [5] ./src/MyFont.woff 83 bytes {0} [built] [6] ./~/style-loader/lib/addStyles.js 8.7 kB {0} [built] [7] ./~/style-loader/lib/urls.js 3.01 kB {0} [built] [8] (webpack)/buildin/global.js 509 bytes {0} [built] [9] (webpack)/buildin/module.js 517 bytes {0} [built] [10] ./src/index.js 503 bytes {0} [built]
Open up index.html again and see if our Hello webpack text has changed to the new font. If all is well, you should see the changes.
再一次打开咱们的index.html
,咱们将看到咱们的文本换成了新的字体,若是一切进展顺利,你就应当可以看到这改变。
Another useful asset that can be loaded is data, like JSON files, CSVs, TSVs, and XML. Support for JSON is actually built-in, similar to NodeJS, meaning import Data from './data.json' will work by default. To import CSVs, TSVs, and XML you could use the csv-loader and xml-loader. Let's handle loading all three:
另外,有用的资源还多是须要加载的数据,就比方说JSON文件、CSV文件、TSV文件、XML文件……对JSON
的支持其实是内置的,相似于NodeJS
,就是说从./data.json
导入数据是会被默认执行的。要导入CSV
,TSV
和XML
,您可使用csv-loader
和xml-loader
。让咱们来处理加载全部三个:
npm install --save-dev csv-loader xml-loader
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' + ] + } ] } };
Add some data files to your 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
<?xml version="1.0" encoding="UTF-8"?> <note> <to>Mary</to> <from>John</from> <heading>Reminder</heading> <body>Call Cindy on Tuesday</body> </note>
Now you can import any one of those four types of data (JSON, CSV, TSV, XML) and the Data variable you import it to will contain parsed JSON for easy consumption:
如今,你能够导入JSON、CSV、TSV、XML中任意一种数据文件,而且数据将导入到变量并包含已解析的JSON,以便于后续的使用:
import _ from 'lodash'; import './style.css'; import Icon from './icon.png'; + import Data from './data.xml'; function component() { var 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. var myIcon = new Image(); myIcon.src = Icon; element.appendChild(myIcon); + console.log(Data); return element; } document.body.appendChild(component());
When you open index.html and look at your console in your developer tools, you should be able to see your imported data being logged to the console!
当你打开index.html
的时候,请观察你的开发工具的控制台输出,你应该可以看到导入的数据已经被打印到控制台上了。
This can be especially helpful when implementing some sort of data visualization using a tool like d3. Instead of making an ajax request and parsing the data at runtime you can load it into your module during the build process so that the parsed data is ready to go as soon as the module hits the browser.
这在使用像D3
这样的工具来进行数据可视化的时候是很是有用的。你能够在编译进行的期间将数据加载到你的模块里,而不是使用一个ajax请求而后解析数据,这样,只要模块一运行在浏览器中,解析后的数据就已经准备好了。
The coolest part of everything mentioned above, is that loading assets this way allows you to group modules and assets together in a more intuitive way. Instead of relying on a global /assets directory that contains everything, you can group assets with the code that uses them. For example, a structure like this can be very useful:
上面提到的全部的事情中最酷的部分是,经过这种方式加载资源可让您以更直观的方式将模块和资源组织在一块儿。根据资源和代码之间的使用关系来对资源进行分组,而不是将它们包含在一个全局的资源文件夹下。例如,像这样的结构可能很是有用:
- |- /assets + |– /components + | |– /my-component + | | |– index.jsx + | | |– index.css + | | |– icon.svg + | | |– img.png
This setup makes your code a lot more portable as everything that is closely coupled now lives together. Let's say you want to use /my-component in another project, simply copy or move it into the /components directory over there. As long as you've installed any external dependencies and your configuration has the same loaders defined, you should be good to go.
这个设置使得你的代码更加轻便,由于如今全部紧密耦合的东西都在一块儿了。假设您想让/my-component
在另外一个项目中使用,只需将其复制或移动到/components
那里的目录便可。只要你已经安装了任何外部的依赖关系,而且你的配置已经定义了相同的loader
。
However, let's say you're locked into your old ways or you have some assets that are shared between multiple components (views, templates, modules, etc.). It's still possible to store these assets in a base directory and even use aliasing to make them easier to import.
然而,假设您已经被旧的方式束缚,或者您拥有一些在多个组件(视图,模板,模块等)之间共享的资源。仍然能够将这些资源存储在基本目录中,甚至可使用别名来使它们更容易导入。
For the next guides we won't be using all the different assets we've used in this guide, so let's do some cleanup so we're prepared for the next piece of the guides Output Management:
对于下一个指南,咱们将不会使用咱们在本指南中使用过的全部不一样资源,因此咱们来作一些清理工做,以便为下一部分指南作好准备。输出管理:
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
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' - ] - } - ] - } };
import _ from 'lodash'; - import './style.css'; - import Icon from './icon.png'; - import Data from './data.xml'; - function component() { var 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. - var myIcon = new Image(); - myIcon.src = Icon; - - element.appendChild(myIcon); - - console.log(Data); return element; } document.body.appendChild(component());