目录
webpack 配置
从 v4.0.0 开始,webpack 开箱即用,可以无需使用任何配置文件。然而,webpack 会假定项目的入口起点为 src/index.js
,然后会在 dist/main.js
输出结果,并且在生产环境开启压缩和优化。
通常你的项目还需要继续扩展此能力,为此你可以在项目根目录下创建一个 webpack.config.js
文件,然后 webpack 会自动使用它。
在开始前你需要先理解一些核心概念:
入口(entry)
入口起点(entry point) 指示 webpack 应该使用哪个模块,来作为构建其内部依赖图(dependency graph) 的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。
默认值是 ./src/index.js
,但你可以通过在 webpack configuration 中配置 entry
属性,来指定一个(或多个)不同的入口起点。例如:
webpack.config.js
// 单个入口语法
module.exports = {
entry: './src/app.js',
};
module.exports = {
entry: ['./src/app.js', './src/search.js'],
};
// 多个入口,对象语法
module.exports = {
entry: {
app: './src/app.js',
search: './src/search.js',
},
};
对象语法会比较繁琐。然而,这是应用程序中定义入口的最可扩展的方式。
输出(output)
output 属性告诉 webpack 在哪里输出它所创建的 bundle,以及如何命名这些文件。主要输出文件的默认值是 ./dist/main.js
,其他生成文件默认放置在 ./dist
文件夹中。
你可以通过在配置中指定一个 output
字段,来配置这些处理过程:
webpack.config.js
const path = require('path');
module.exports = {
entry: './src/app.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
},
};
在上面的示例中,我们通过 output.filename
和 output.path
属性,来告诉 webpack bundle 的名称,以及我们想要 bundle 生成到哪里。在代码最上面导入的 path 模块它是一个 Node.js 核心模块,用于操作文件路径。
如果配置中使用多个入口起点或使用像 CommonsChunkPlugin 这样的插件,则应该使用占位符(substitutions) 来确保每个文件具有唯一的名称:
module.exports = {
entry: {
app: './src/app.js',
search: './src/search.js',
},
output: {
filename: '[name].js',
path: __dirname + '/dist',
},
};
// 写入到硬盘:./dist/app.js, ./dist/search.js
loader
webpack 只能理解 JavaScript 和 JSON 文件,这是 webpack 开箱可用的自带能力。在开发中我们不仅仅有基本的 js代码处理,我们也需要加载 css、图片,也包括一些高级的将 ES6 转成 ES5 代码,将 TypeScript 转成 ES5 代码,将scss、less 转成 css,将 .jsx、.vue文件转成 js 文件, loader 让 webpack 能够去处理这些类型的文件,并将它们转换为有效 模块,以供应用程序使用,以及被添加到依赖图中。
在 webpack 的配置中,loader 有两个属性:
配置文件:
module.exports = {
output: {
filename: 'bundle.js',
},
module: {
rules: [{ test: /\.txt$/, use: 'raw-loader' }],
},
};
以上配置中,对一个单独的 module 对象定义了 rules
属性,里面包含两个必须属性:test
和 use
。这告诉 webpack 编译器(compiler)当碰到在* require()
/import
语句中被解析为 '.txt' 的路径时,在你对它打包之前,先 use(使用) raw-loader
转换一下。
下面介绍几种常用的 loader。
加载 css
css-loader
会对 @import
和 url()
进行处理,就像 js 解析 import/require()
一样。style-loader
将模块导出的内容作为样式并添加到 DOM 中。
安装 style-loader
和 css-loader
:
npm install style-loader css-loader --save-dev
src/css/index.css
body {
background: green;
}
在入口文件中引用:
require('./css/index.css')
然后将该 loader 添加到 webpack
的配置中去:
const path = require('path')
module.exports = {
entry: {
index : './src/index.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
},
module :{
rules: [
{test: /\.css$/, use: ['style-loader', 'css-loader']},
]
}
}
注意:style-loader 必须放在 css-loader 前。这次因为 webpack 在读取使用的 loader 的过程中,是按照从右向左的顺序读取的。
编译 less
webpack 将 Less 编译为 CSS 的 loader
先安装 less
和 less-loader
:
npm install less less-loader --save-dev
src/css/index.less
@fontSize: 40px;
@fontColor: red;
body {
font-size: @fontSize;
color: @fontColor;
}
在入口文件中引用:
require('./css/index.less')
然后将该 loader 添加到 webpack
的配置中去:
const path = require('path')
module.exports = {
entry: {
index : './src/index.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
},
module :{
rules: [
{test: /\.less$/, use: ['style-loader', 'css-loader', 'less-loader']},
]
}
}
图片文件处理
file-loader
将一个文件中的 import
/require()
解析为 url,并且将文件发送到输出文件夹,默认 dist
。
v5 版本已废弃。
先安装 file-loader
:
npm install file-loader --save-dev
src/img/index.jpg 11.3 KB
src/css/index.css
body {
background: green;
color: white;
background-image: url(../img/index.jpg);
}
在入口文件中引用:
require('./css/index.css')
require('./../img/index.jpg')
然后将该 loader 添加到 webpack
的配置中去:
const path = require('path')
module.exports = {
entry: {
index : './src/index.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
},
module :{
rules: [
{test: /\.css$/, use: ['style-loader', 'css-loader']},
{test: /\.(png|jpe?g|gif)$/,
use:[
{
loader:'file-loader',
},
]
},
]
}
}
我们发现 webpack 自动帮助我们生成一个非常长的名字,这是一个32位 hash 值,目的是防止名字重复。但是,真实开发中,我们可能对打包的图片名字有一定的要求,比如,将所有的图片放在一个文件夹中,跟上图片原来的名称,同时也要防止重复所以,我们可以在options中添加上如下选项:
{test: /\.(png|jpe?g|gif)$/,
use:[
{
loader:'file-loader',
options: {
name: 'img/[name]-[hash:8].[ext]'
},
},
]
},
hash:8
:为了防止图片名称冲突,依然使用hash,但是我们只保留8位
ext
:使用图片原来的扩展名
url-loader
用于将文件转换为 base64 URI 的 loader。
v5 版本已废弃。
先安装 url-loader
:
npm install url-loader --save-dev
url-loader
功能类似于 file-loader
, 但是在文件大小(单位为字节)低于指定的限制时,可以返回一个 DataURL。
const path = require('path')
module.exports = {
entry: {
index : './src/index.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
},
module :{
rules: [
{test: /\.css$/, use: ['style-loader', 'css-loader']},
{test: /\.(png|jpe?g|gif)$/,
use:[
{
loader:'url-loader',
options: {
limit:15000
},
},
]
},
]
}
}
使用 babel-loader
转换 ES6
目前,ES6(ES2015)这样的语法已经得到很大规模的应用,它具有更加简洁、功能更加强大的特点,实际项目中很可能会使用采用了 ES6 语法的模块,但浏览器对于 ES6 语法的支持并不完善。为了实现兼容,就需要使用转换工具对 ES6 语法转换为 ES5 语法,babel 就是最常用的一个工具。
babel转化语法所需依赖项:
babel-loader: 负责 es6 语法转化
babel-core: babel核心包
babel-preset-env:告诉 babel 使用哪种转码规则进行文件处理
安装:
npm install babel-loader @babel/core @babel/preset-env --save-dev
然后将这些 loader 添加到 webpack
的配置中去:
const path = require('path')
module.exports = {
entry: {
index : './src/index.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
},
module :{
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
}
}