By default, Webpack only handles JS files. If you want to process other files, WebPack needs to configure loaders to preprocess the files so that WebPack can process arbitrary static resources. Common webpack loaders for handling static resources include file-loader, URl-loader, CSS-loader, and style-loader respectively. I will analyze the use of these loaders in the following examples.

Create a Webpack project

Our Webpack project directory is shown below, with static resources including images and fonts placed under SRC/Assets

scr/index.js
dist/js/bundle.js

// webpack.config.js const path = require('path'); const { CleanWebpackPlugin } = require('clean-webpack-plugin'); module.exports = { mode: 'none', entry: './src/index.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'js/bundle.js',}, plugins: [new CleanWebpackPlugin() // For testing convenience, we use CleanWebpackPlugin to clean up the previous package before the next package]}; // src/index.js import './style.css' // src/style.css #app { font-family: 'BalsamiqSans'; width: 100vw; height: 100vh; }Copy the code

At this time, the console runs the package command NPM run build, and an error message is reported as follows

ERROR in ./src/style.css
Module parse failed: Unexpected character The '@' (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file
Copy the code

As stated at the beginning, webPack only packages JS files by default, and our entry file contains not only JS files but also CSS files, so WebPack reported an error.

2. Run style-loader css-loader to process CSS files

• Style-loader is used to inject CSS into the DOM. Style-loader must be used together with CSS-loader

• CSS-loader is used to parse @import and URL () as import/require()

We improved the configuration of Webpack:

const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
  mode: 'none'.entry: './src/index.js'.output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'js/bundle.js',},module: {
    rules: [{test: /\.css$/i.use: ['style-loader'.'css-loader'],},],},plugins: [
    new CleanWebpackPlugin(),
  ]
};
Copy the code

There is no error when the bundle is successfully packaged, but you will notice that there is only one bundle.js file and the CSS code is injected into the bundle.js file. We can extract CSS into a separate file using the MiniCssExtractPlugin plugin. Please note that MiniCssExtractPlugin. Loader and style – loader will conflict, when both exist at the same time, complains the document is not defined

const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
  mode: 'none'.entry: './src/index.js'.output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'js/bundle.js',},module: {
    rules: [{test: /\.css$/i.use: [MiniCssExtractPlugin.loader, 'css-loader'],},],},plugins: [
    new CleanWebpackPlugin(),
    new MiniCssExtractPlugin({
      filename: 'css/[name].css'}})];Copy the code

Successfully packaged JS and CSS files, and output to the desired file path

3. Use file-loader url-loader to process static resources

• File-loader is used to process static resources such as fonts, images, etc., inject resources into webpack, and resolve resource dependencies

• Url-loader functions similar to file-loader and can set the file size. When the resource is less than the limit, a DataURL can be returned, which is injected into the file as base64 encoding. Basically, the image data is translated into a string of characters, and the string of characters is packaged into a file so that the file can access the image

Font resources and image resources are prepared in the project, and the configuration of Webpack is further updated:

// src/style.css
@font-face {
  font-family: 'BalsamiqSans';
  src: url('./assets/fonts/BalsamiqSans-Bold.ttf');
}
#app {
  font-family: 'BalsamiqSans';
  background: url('./assets/image/mai.png');
  width: 100vw;
  height: 100vh;
}
Copy the code
const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
  mode: 'none'.entry: './src/index.js'.output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'js/bundle.js',},module: {
    rules: [{test: /\.(png|jpe? g|gif)$/i.loader: 'url-loader'.options: {
          name: '[name].[ext]'.limit: 8900.outputPath: 'img'}, {},test: /\.(woff|woff2|eot|ttf|otf|)$/.loader: 'file-loader'.options: {
          name: '[name].[ext]'.outputPath: 'fonts'}, {},test: /\.css$/i.use: [MiniCssExtractPlugin.loader, 'css-loader'],},],},plugins: [
    new CleanWebpackPlugin(),
    new MiniCssExtractPlugin({
      filename: 'css/[name].css'}})];Copy the code

As expected, we successfully packaged the JS file with the static resource file.


      
<head>
  <title> webpack-demos </title>
  <link rel="stylesheet" type="text/css" href="./dist/css/main.css">
</head>
<body>
  <div id="app">
    hello world
    <script src="./dist/js/bundle.js"></script>
  </div>
</body>
Copy the code

Unfortunately, the packaged resource path was not found

An absolute path
dist/img/mai.png
dist/css/img/mai.png

const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
  mode: 'none'.entry: './src/index.js'.output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'js/bundle.js',},module: {
    rules: [{test: /\.(png|jpe? g|gif)$/i.loader: 'url-loader'.options: {
          name: '[name].[ext]'.limit: 8900.outputPath: 'img'}, {},test: /\.(woff|woff2|eot|ttf|otf|)$/.loader: 'file-loader'.options: {
          name: '[name].[ext]'.outputPath: 'fonts'}, {},test: /\.css$/i.use: [{loader: MiniCssExtractPlugin.loader,
            options: {
              publicPath: '.. / '.// CSS has one more layer}},'css-loader'],},],},plugins: [
    new CleanWebpackPlugin(),
    new MiniCssExtractPlugin({
      filename: 'css/[name].css'}})];Copy the code

At this point, the packaged static resource configuration path reference is normal.

@font-face {
  font-family: 'BalsamiqSans';
  src: url(.. /fonts/BalsamiqSans-Bold.ttf); }#app {
  font-family: 'BalsamiqSans';
  background: url(.. /img/mai.png);width: 100vw;
  height: 100vh;
}
Copy the code

So far, the use of Webpack successfully compiled JS files, image fonts and other resource files, and analyzed the problem of static resource packaging path. You might think this article is over, but it isn’t. In a Vue project, static resources can be placed in the root directory under the public folder and the SRC /assets folder. What is the difference between these two paths?

4. Webpack handles static resources

How does WebPack handle static resources? In the previous section, we described how loaders handle static resources. In a Vue project, the template and CSS are resolved by vue-loader and CSS-loader respectively. For example, and background: URL (./logo.png), “./logo.png” is a relative resource path that will be resolved by Webpack as a module dependency. Logo.png is not JavaScript, and when used as a module dependency, we need to use url-loader and file-loader for processing. Since these resources may be inlined/copied/renamed during the build process, they can be made part of the source code. Therefore, it is recommended to place the resource files in the SRC directory along with other source files. You don’t have to put assets in SRC /assets. You can put them in modules/components. For example, static resources can be placed in each directory where components are placed. Files placed in the public directory are not processed by Webpack and are copied directly to the final directory (dist/static by default). These files must be referenced using an absolute path.

Webpack is a package modularization tool, in Webpack all files are modules. This article introduces how to parse files by loaders and how to process static resources step by step by file-loader, URL-loader, CSS-loader and style-loader. Compare the two differences in placing static resources in a Vue project. Resources placed under SRC/Assets are packaged by Webpack at build time into the final output file, which is suitable for placing resources in the project. Files under public are not processed by WebPack at build time and will be copied directly to the final path and referenced, so it is suitable to place some third-party library files.

Reference: Handling Static Assets