Hi everyone, for frontend devs, everyone knows and uses webpack
through webpack
right? At least read through config snippets like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | module <span class="token punctuation">.</span> exports <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token operator">...</span> <span class="token punctuation">,</span> module <span class="token operator">:</span> <span class="token punctuation">{</span> rules <span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token punctuation">{</span> test <span class="token operator">:</span> <span class="token regex">/.(eot|otf|ttf|woff|woff2)$/</span> <span class="token punctuation">,</span> use <span class="token operator">:</span> <span class="token string">'file-loader'</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">{</span> test <span class="token operator">:</span> <span class="token regex">/.(jpg|png|gif)$/</span> <span class="token punctuation">,</span> use <span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token punctuation">{</span> loader <span class="token operator">:</span> <span class="token string">'url-loader'</span> <span class="token punctuation">,</span> options <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token comment">// Inline files smaller than 10 kB</span> limit <span class="token operator">:</span> <span class="token number">10</span> <span class="token operator">*</span> <span class="token number">1024</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">]</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token operator">...</span> <span class="token punctuation">]</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">;</span> |
At first, I just watched. After the free time, init source also copy + paste => app runs ok. Then don’t care anymore
However, today I will try to lightly debug some loaders to see how they work, and why each different file type has to use different loaders. Specifically, in this article I will try to debug file-loader
, url-loader
, … differently. OK, let’s go
Prepare
First I will create a few files + folders as follows.
1 2 3 4 5 6 7 8 9 10 11 | ├── dist/ │ └── index.html // script mình trỏ tới main.js (default lúc build ra) ├── src/ │ └── assets/ │ │ └── (file và ảnh linh tinh gì cũng được) │ └── index.js (file trống, tý thêm code sau) ├── webpack/ │ └── config.js ├── ... ├── package.json |
Everyone remember to add the build
script
1 2 3 4 | <span class="token property">"scripts"</span> <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token property">"build"</span> <span class="token operator">:</span> <span class="token string">"webpack --config webpack/config.js"</span> <span class="token punctuation">}</span> |
Next we will go to the debug tab => create file launch.json
=> select Node js
to debug some file loader
We will update the launch.json
file again as follows (I use yarn
here)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <span class="token punctuation">{</span> <span class="token comment">// Use IntelliSense to learn about possible attributes.</span> <span class="token comment">// Hover to view descriptions of existing attributes.</span> <span class="token comment">// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387</span> <span class="token property">"version"</span> <span class="token operator">:</span> <span class="token string">"0.2.0"</span> <span class="token punctuation">,</span> <span class="token property">"configurations"</span> <span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token punctuation">{</span> <span class="token property">"type"</span> <span class="token operator">:</span> <span class="token string">"node"</span> <span class="token punctuation">,</span> <span class="token property">"request"</span> <span class="token operator">:</span> <span class="token string">"launch"</span> <span class="token punctuation">,</span> <span class="token property">"name"</span> <span class="token operator">:</span> <span class="token string">"Launch build"</span> <span class="token punctuation">,</span> <span class="token property">"cwd"</span> <span class="token operator">:</span> <span class="token string">"${workspaceFolder}"</span> <span class="token punctuation">,</span> <span class="token property">"runtimeExecutable"</span> <span class="token operator">:</span> <span class="token string">"yarn"</span> <span class="token punctuation">,</span> <span class="token property">"runtimeArgs"</span> <span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token string">"build"</span> <span class="token punctuation">]</span> <span class="token punctuation">}</span> <span class="token punctuation">]</span> <span class="token punctuation">}</span> |
Now let’s debug >>
Refer to nodejs debug
: https://code.visualstudio.com/docs/nodejs/nodejs-debugging
file-loader
First, we will play with the file-loader
Docs: https://webpack.js.org/loaders/file-loader/
The file-loader resolves import / require () on a file into a url and emits the file into the output directory.
According to the docs, the file-loader
has two uses: emit
(copy + hash file name, …) the file from the src
folder to the dist
folder and returns the url
of the file for us to import
We will add the following code to the index.js
file for testing
1 2 3 4 | <span class="token keyword">import</span> imgUrl <span class="token keyword">from</span> <span class="token string">"./assets/images/image1.jpg"</span> <span class="token punctuation">;</span> document <span class="token punctuation">.</span> <span class="token function">getElementById</span> <span class="token punctuation">(</span> <span class="token string">"image"</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> src <span class="token operator">=</span> imgUrl <span class="token punctuation">;</span> |
To debug
, we will go to node_modules
find the file-loader
folder to set breakpoint
Then go to the debug tab and run launch build
You may notice that the file name was changed back to the default structure of [contenthash].[ext]
and then emit into the outputPath
(this function is provided by webpack
).
1 2 3 4 | <span class="token keyword">this</span> <span class="token punctuation">.</span> <span class="token function">emitFile</span> <span class="token punctuation">(</span> outputPath <span class="token punctuation">,</span> content <span class="token punctuation">,</span> <span class="token keyword">null</span> <span class="token punctuation">,</span> <span class="token punctuation">{</span> immutable <span class="token punctuation">}</span> <span class="token punctuation">)</span> <span class="token punctuation">;</span> |
The return will have an export default ${outputPath}
, in my opinion, webpack
will eval
this string (guess: v)
Result:
Refer to the structure of the loader
: https://webpack.js.org/contribute/writing-a-loader/
Refer to the loaders
interface: https://webpack.js.org/api/loaders/#thisemitfile
url-loader
Docs: https://webpack.js.org/loaders/url-loader/
url-loader works like file-loader, but can return a DataURL if the file is smaller than a byte limit.
url-loader
is similar to file-loader
, it only has function return base64
url instead of normal url for small file size.
We will update the webpack.config.js
file again as follows
1 2 3 4 5 6 7 8 9 10 11 12 13 | <span class="token punctuation">{</span> test <span class="token operator">:</span> <span class="token regex">/.(jpg|png|gif)$/</span> <span class="token punctuation">,</span> use <span class="token operator">:</span> <span class="token punctuation">[</span> <span class="token punctuation">{</span> loader <span class="token operator">:</span> <span class="token string">"url-loader"</span> <span class="token punctuation">,</span> options <span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token comment">// limit 100 KB</span> limit <span class="token operator">:</span> <span class="token number">1024</span> <span class="token operator">*</span> <span class="token number">100</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> <span class="token punctuation">]</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> |
And debug:
As you can see, because my image file is small (<100kb), the url-loader
has been encode
and returned as base64
url. Cool !!
Result
raw-loader
Now I’ll try adding the last one and concluding the lesson >>
Now we will import
file hello.txt
and use the raw-loader
to load the content
1 2 3 4 5 6 7 | <span class="token comment">// src/index.js</span> <span class="token keyword">import</span> imgUrl <span class="token keyword">from</span> <span class="token string">"./assets/images/image1.jpg"</span> <span class="token punctuation">;</span> <span class="token keyword">import</span> content <span class="token keyword">from</span> <span class="token string">"./assets/files/hello.txt"</span> <span class="token punctuation">;</span> document <span class="token punctuation">.</span> <span class="token function">getElementById</span> <span class="token punctuation">(</span> <span class="token string">"image"</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> src <span class="token operator">=</span> imgUrl <span class="token punctuation">;</span> document <span class="token punctuation">.</span> <span class="token function">getElementById</span> <span class="token punctuation">(</span> <span class="token string">"text"</span> <span class="token punctuation">)</span> <span class="token punctuation">.</span> textContent <span class="token operator">=</span> content <span class="token punctuation">;</span> |
1 2 3 4 5 6 7 | <span class="token comment">// webpack/config.js</span> <span class="token operator">...</span> <span class="token punctuation">{</span> test <span class="token operator">:</span> <span class="token regex">/.txt$/</span> <span class="token punctuation">,</span> use <span class="token operator">:</span> <span class="token string">"raw-loader"</span> <span class="token punctuation">,</span> <span class="token punctuation">}</span> <span class="token punctuation">,</span> |
debug
similar to the previous 2 loader
, we will see the raw-loader
will return the contents of the file instead of the url
Result:
Here, I add white-space: pre-line
to newline.
OK. accomplished
Conclusion
Posts come here only. Hope to help everyone understand more about webpack loader
and how they work. Wished everyone success