Webpack配置

Webpack配置

Kotlin看不动了,摸鱼学学前端。

先安装node.js和npm,此处略。

初始化

初始化package描述文件,在项目路径中生成package.json文件。

npm init

或者使用npm init --yes省去中间配置步骤。

安装Webpack

npm i webpack webpack-cli -D

–save-dev(-D)参数意思是把模块版本信息保存到devDependencies(开发环境依赖)中,即package.json的devDependencies字段中

配置build启动脚本

package.json中,对scripts添加build字段:

{
  "scripts": {
    "build": "webpack --mode production",
    "test": "echo \"Error: no test specified\" && exit 1"
  }
}

此外在项目目录中新建文件夹src作为源码目录,在src中新建文件index.js作为程序入口,内容随便写点。

此时可以测试能否build成功:

npm run build

项目目录中会出现一个dist文件夹,里面有一个main.js,即转换生成的js文件。

使用webpack.config.js

可以使用webpack.config.js来自定义build的入口和出口。该文件可以使用node.js的模块。

const path = require("path");

module.exports = {
    entry: './src/home.js',
    output: {
        path: path.resolve(__dirname, "dist"),
        filename: 'output.js'
    }
}

requirenode.js引入模块的方法。此处引入的path是用于处理操作系统中文件路径的模块。path.resolve()方法将路径转换为绝对路径。__dirname为当前执行文件所在目录的完整目录名。

如果需要有多个入口和多个出口,可以如下配置:

const path = require("path");

module.exports = {
    entry: {
        main: './src/home.js',
        about: './src/about.js'
    },
    output: {
        path: path.resolve(__dirname, "dist"),
        filename: '[name].js'
    }
};

output可以省略,生成的文件名使用entry中对应的key值。[name]是由webpack自动填充的字段。还可以使用[hash][chunkHash]来生成hash值。

webpack.config.js的位置也是可配置的,需要修改package.json - scripts - build字段

{ 
  "scripts": {
    "build": "webpack --mode production --config scripts/webpack.config.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  }
}

此时webpack的当前路径变为./scripts/,因此还需要修改webpack.config.js

const path = require("path");
const dist = path.join(__dirname, '..', 'dist');

module.exports = {
    entry: {
        main: './src/home.js',
        about: './src/about.js'
    },
    output: {
        path: dist,
        filename: '[name].js'
    }
};

或者

const path = require("path");

module.exports = {
    entry: {
        main: './src/home.js',
        about: './src/about.js'
    },
    output: {
        path: path.resolve(process.cwd(), "dist"),
        filename: '[name].js'
    }
};

process.cwd()为获得当前执行node命令时候的文件夹目录名。

自动生成html

如果生成js使用了hash值作为文件名,那么对应的html也需要自动生成。安装插件html-webpack-plugin

npm i -D html-webpack-plugin

webpack.config.js中加入插件:

const path = require("path");
// 引入模块
const HtmlWebpackPlugin =require("html-webpack-plugin");
const dist = path.join(__dirname, '..', 'dist');

module.exports = {
    entry: {
        main: './src/home.js',
    },
    output: {
        path: dist,
        filename: '[name].[chunkHash:8].js'
    },
    // 引入插件
    plugins: [
            new HtmlWebpackPlugin()
    ]
};

进行npm run build,在dist中生成了index.html,其中使用的js文件是打包的js文件。

html模版

使用html模版则需要在项目目录中建立public文件夹,在其中建立home.html,如下:

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>自动生成模版</title>
</head>
<body>
<div id="root"></div>
</body>
</html>

修改webpack.config.js,为插件添加配置:

const path = require("path");
const HtmlWebpackPlugin =require("html-webpack-plugin");
const dist = path.join(__dirname, '..', 'dist');

module.exports = {
    entry: {
        main: './src/home.js',
    },
    output: {
        path: dist,
        filename: '[name].[chunkHash:8].js'
    },
    plugins: [
            new HtmlWebpackPlugin({
                title: "模版测试",
                template: "public/home.html"
            })
    ]
};

可以使用模版语法来定制生成的html。

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<div id="root"></div>
</body>
</html>

再次打包则生成的html如下:

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>模版测试</title>
</head>
<body>
<div id="root"></div>
<script type="text/javascript" src="main.299861a9.js"></script></body>
</html>

css

安装style-loadercss-loaderstyle-loader用于插入css到js里。css-loader用于处理css。

npm i -D style-loader css-loader

修改webpack.config.js,添加loader:

const path = require("path");
const HtmlWebpackPlugin =require("html-webpack-plugin");
const dist = path.join(__dirname, '..', 'dist');

module.exports = {
    entry: {
        main: './src/home.js',
    },
    output: {
        path: dist,
        filename: '[name].[chunkHash:8].js'
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [ 'style-loader', 'css-loader' ]
            }
        ]
    },
    plugins: [
            new HtmlWebpackPlugin({
                title: "模版测试",
                template: "public/home.html"
            })
    ]
};

loader的执行顺序从后向前。

在js文件中引入css。

import './main.css';
console.log("home");

此时进行打包,css会进入js并在执行的时候生效。

如果希望提取css到单独文件,则需要安装mini-css-extract-plugin插件。

npm i -D mini-css-extract-plugin

修改webpack.config.js,加入该插件的配置,修改位置已标出。

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
// [1]
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

const dist = path.join(__dirname, '..', 'dist');

module.exports = {
    entry: {
        main: './src/home.js',
    },
    output: {
        path: dist,
        filename: '[name].[chunkHash:8].js'
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                // [2]
                use: [ MiniCssExtractPlugin.loader, 'css-loader' ]
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            title: "模版测试",
            template: "public/home.html"
        }),
        // [3]
        new MiniCssExtractPlugin({
            filename: '[name].css'
        })
    ]
};

进行打包时css文件会单独到处,并在html中引入。

构建导出目录结构

修改webpack.config.js,直接在导出部分添加路径即可。

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

const dist = path.join(__dirname, '..', 'dist');

module.exports = {
    entry: {
        main: './src/home.js',
    },
    output: {
        path: dist,
        // [1]
        filename: 'js/[name].[chunkHash:8].js'
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [ MiniCssExtractPlugin.loader, 'css-loader' ]
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            title: "模版测试",
            template: "public/home.html"
        }),
        new MiniCssExtractPlugin({
            // [2]
            filename: 'css/[name].[chunkHash:8].css'
        })
    ]
};

配置开发服务器

安装插件webpack-dev-server

npm i -D webpack-dev-server

修改package.json,添加dev命令。

{
  "name": "test-react-2",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "webpack --mode production --config scripts/webpack.config.js",
    "dev": "webpack-dev-server --mode development --config scripts/webpack.config.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "css-loader": "^3.2.0",
    "html-webpack-plugin": "^3.2.0",
    "mini-css-extract-plugin": "^0.8.0",
    "style-loader": "^1.0.0",
    "webpack": "^4.41.2",
    "webpack-cli": "^3.3.9"
  }
}

修改webpack.config.js,可以配置端口号等。

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

const dist = path.join(__dirname, '..', 'dist');

module.exports = {
    entry: {
        main: './src/home.js',
    },
    output: {
        path: dist,
        filename: 'js/[name].[chunkHash:8].js'
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [ MiniCssExtractPlugin.loader, 'css-loader' ]
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            title: "模版测试",
            template: "public/home.html"
        }),
        new MiniCssExtractPlugin({
            filename: 'css/[name].[chunkHash:8].css'
        })
    ],
    // [1]
    devServer: {
        port: 3000,
        open: true
    }
};

配置css预处理器

安装lessless-loader

npm i -D less less-loader

修改webpack.config.js,添加less文件规则。

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

const dist = path.join(__dirname, '..', 'dist');

module.exports = {
    entry: {
        main: './src/home.js',
    },
    output: {
        path: dist,
        filename: 'js/[name].[chunkHash:8].js'
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [ MiniCssExtractPlugin.loader, 'css-loader' ]
            },
            // [1]
            {
                test: /\.less$/,
                use: [ MiniCssExtractPlugin.loader, 'css-loader', 'less-loader' ]
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            title: "模版测试",
            template: "public/home.html"
        }),
        new MiniCssExtractPlugin({
            filename: 'css/[name].[chunkHash:8].css'
        })
    ],
    devServer: {
        port: 3000,
        open: true
    }
};

添加一个less文件并引入。

body {
  color: aliceblue;
}
import './main.css'
// [1]
import './test.less'
console.log("home");

图片处理

安装file-loader

npm i -D file-loader

webpack.config.js中配置规则。

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

const dist = path.join(__dirname, '..', 'dist');

module.exports = {
    entry: {
        main: './src/home.js',
    },
    output: {
        path: dist,
        filename: 'js/[name].[chunkHash:8].js'
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [MiniCssExtractPlugin.loader, 'css-loader']
            },
            {
                test: /\.less$/,
                use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader']
            },
            // [1]
            {
                test: /\.(png|jpe?g|gif|jfif)$/i,
                use: [
                    {
                        loader: 'file-loader',
                    },
                ],
                options: {
                    name: '[path][name].[ext]',
                }
            },
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            title: "模版测试",
            template: "public/home.html"
        }),
        new MiniCssExtractPlugin({
            filename: 'css/[name].[chunkHash:8].css'
        })
    ],
    devServer: {
        port: 3000,
        open: true
    }
};

字体处理

同样使用file-loader。在webpack.config.js中添加配置。

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

const dist = path.join(__dirname, '..', 'dist');

module.exports = {
    entry: {
        main: './src/home.js',
    },
    output: {
        path: dist,
        filename: 'js/[name].[chunkHash:8].js'
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [MiniCssExtractPlugin.loader, 'css-loader']
            },
            {
                test: /\.less$/,
                use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader']
            },
            {
                test: /\.(png|jpe?g|gif|jfif)$/i,
                loader: 'file-loader',
                options: {
                    name: 'static/images/[name].[ext]',
                    publicPath: '/'
                }
            },
            // [1]
            {
                test: /\.(eot|ttf|woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
                loader: 'file-loader',
                options: {
                    name: 'static/fonts/[name].[ext]',
                    publicPath: '/'
                }
            },
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            title: "模版测试",
            template: "public/home.html"
        }),
        new MiniCssExtractPlugin({
            filename: 'static/css/[name].[chunkHash:8].css'
        })
    ],
    devServer: {
        port: 3000,
        open: true
    }
};

修改less。

@mainColor: aliceblue;
.textHover(@origin: aqua, @hover: #44cccc) {
  color: @origin;
  &:hover {
    color: @hover;
  }
}

// [1]
@font-face {
  font-family: FFXIV_Lodestone_SSF;
  src: url("assets/fonts/FFXIV_Lodestone_SSF.woff") format('woff');
}
body {
  color: @mainColor;

  h1 {
    color: coral;
  }

  #text1 {
    .textHover;
  }

  #text2 {
    .textHover(pink, #dda0ba);
  }

  // [2]
  #text3 {
    font-family: FFXIV_Lodestone_SSF, serif;
  }
}

配置babel

babel可以把ES2015及更新版本的js转换为向前兼容的js,也支持转换jsx。

安装babel-loader

npm i -D babel-loader @babel/core @babel/preset-env

webpack.config.js中添加规则。

const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

const dist = path.join(__dirname, '..', 'dist');

module.exports = {
    entry: {
        main: './src/home.js',
    },
    output: {
        path: dist,
        filename: 'js/[name].[chunkHash:8].js'
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: [MiniCssExtractPlugin.loader, 'css-loader']
            },
            {
                test: /\.less$/,
                use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader']
            },
            {
                test: /\.(png|jpe?g|gif|jfif)$/i,
                loader: 'file-loader',
                options: {
                    name: 'static/images/[name].[ext]',
                    publicPath: '/'
                }
            },
            {
                test: /\.(eot|ttf|woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
                loader: 'file-loader',
                options: {
                    name: 'static/fonts/[name].[ext]',
                    publicPath: '/'
                }
            },
            // [1]
            {
                test: /\.m?js$/,
                exclude: /(node_modules|bower_components)/,
                use: {
                    loader: 'babel-loader',
                    options: {
                        presets: ['@babel/preset-env']
                    }
                }
            }
        ]
    },
    plugins: [
        new HtmlWebpackPlugin({
            title: "模版测试",
            template: "public/home.html"
        }),
        new MiniCssExtractPlugin({
            filename: 'static/css/[name].[chunkHash:8].css'
        })
    ],
    devServer: {
        port: 3000,
        open: true
    }
};
Author: SinLapis
Link: http://sinlapis.github.io/2019/10/22/Webpack配置/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.