1.主要概念
- 入口
entry
- 出口
output
- 加载器
loader
- 插件
plugins
- 模式
mode
2.入口 entry
几种用法:
# 1.单个入口 (简写) 语法
# 用法: entry: string | Array<string>
# 如果传入的是字符串数组(即 Array<string> ),将插件多个主入口
# 当你想要将多个依赖文件一起注入,且将他们的依赖稻香到一个 chunk 时
# 传入数组的方式十分有用
const config = {
entry: './path/to/my/entry/file.js',
};
// entry 属性的单个入口语法
const config = {
entry: {
main: './path/to/my/entry/file.js',
},
};
# 2.对象语法
# 用法:entry: {[entryChunkName: string]: string|Array<string>}
# 这样允许使用 'CommonsChunkPlugin' 从app bunlde 中提取vendor应用到 vendor bundle中
# 并将引用vendor的部分替换为 '__webpack_require__()'调用
# 注意:这个场景webpack官方正在考虑使用分离能力更强的DllPlugin来替换这种场景的使用
const config = {
entry: {
app: './src/app.js',
vendors: './src/vendors.js',
},
};
# 3.多页面应用程序
# 告诉webpack需要3个独立分离的依赖图
# 分离的依赖图之间是相互独立的,每个bundle中都有一个webpack引导
# 每当页面跳转时,服务器将获取一个新的HTML文档。
# 页面重新加载新的文档,资源也重新下载
# 但是我们可以使用 CommonsChunkPlugin 为每个页面见的应用程序共享代码创建bundle
const config = {
entry: {
pageOne: './src/pageOne/index.js',
pageTwo: './src/pageTwo/index.js',
pageThree: './src/pageThree/index.js',
},
};
modules.export = config;
3.输出 output
控制webpack如何向硬盘写入编译的文件
# 将其设置为一个对象
# 'filename': 输出文件的文件名
# 'path': 目标输出目录的绝对路径
# 配置一个单独的bundle.js 输出到 '/home/proj/public/assets'目录下
const config = {
output: {
filename: 'bundle.js',
path: '/home/proj/public/assets',
},
};
# 多个入口起点
# 使用多个入口起点或者使用像 CommonsChunkPlugin插件插件创建多个单独的 chunk
# 则应该使用 占位符(substitutions) 来确保每个文件具有唯一的名称
const config = {
// 多个入口
entry: {
app: './src/app.js',
search: './src/search.js',
},
// 写入到硬盘 ./dist/app.js 和 ./dist/search.js
output: {
filename: '[name].js',
output: __dirname + '/dist',
},
};
# 高级用法
# 使用CDN 和 hash的复杂示例
output: {
path: '/home/proj/cdn/assets/[hash]',
// 编译时不知道最终输出文件的 publicPath 情况下,publicPath 可以留空
// 在运行时(at runtime)将在入口文件动态的设置
publicPath: 'http://cdn.example.com/assets/[hash]/',
},
// 如果编译时不知道 publicPath,可以忽略这个字段,并在入口处设置 '__webpack_public_path__'
__webpack_public_path__ = myRuntimePublicPath
// 剩余的应用程序入口
4.模式 mode
告诉webpack使用相应的 process.env.NODE_ENV
值对打包文件进行优化。
2种模式:
-
development
: 启用NamedChunksPlugin
和NamedModulesPlugin
-
Production
: 启用FlagDependencyUsagePlugin
,FlagIncludedChunksPlugin
,ModuleConcatenationPlugin
,NoEmitOnErrorsPlug
,OccurrenceOrderPlugin
,SideEffectsFlagPlugin
和UglifyJsPlugin
// webpack.development.config.js
module.exports = {
+ mode: 'development'
- plugins: [
- new webpack.NamedModulesPlugin(),
- new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") }),
- ]
}
// webpack.production.config.js
module.exports = {
+ mode: 'production',
- plugins: [
- new UglifyJsPlugin(/* ... */),
- new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }),
- new webpack.optimize.ModuleConcatenationPlugin(),
- new webpack.NoEmitOnErrorsPlugin()
- ]
}
5.加载器 loader
在 import
或者 加载模块时对模块的源代码进行转换。类似gulp中的task. 加载器可以将不同的语言,比如typescript,转换为js,或者内联图像转换为data URL;又或者运行在js模块中直接 import css文件。
简单示例:
// 将ts文件转换为js文件
// 在js模块中引入css文件
# 1.先下载需要的loaders
yarn add -D ts-loader css-loader
# 2.在配置文件中使用loader
const config = {
//...
module: {
rules: [
{ test: /\.tsx?$/, use: 'ts-loader' },
{ test: /\.css$/, use: 'css-loader' },
],
},
};
loader的3种使用方式
-
配置文件(
webpack.config.js
)中使用,在module.rules
中指定module: { rules: [ { test: /\.css$/, // loader 将从数组从右向左执行 // 即 css-loader先执行,后执行style-loader use: [ { loader: 'style-loader' }, { loader: 'css-loader', options: { modules: true, }, }, ], }, ], },
-
内联的方式,在每个
import
语句中显示的指定loader# 使用 '!' 将多个loader分开 # 选项可以穿的查询参数,比如 '?key=value&foo=bar' # 或者一个JSON对象,例如 '?{"key": "value", "foo": "bar"}' import Styles from 'style-loader!css-loader?modules!./styles.css'; # 推荐使用第一种方式,即配置文件的形式
-
命令行的形式
# 对 '.jade' 文件使用 'jade-loader' # 对 '.css' 文件使用 'style-loader' 和 'css-loader' > webpack --module-bind jade-loader --module-bind 'css=style-loader!css-loader'
loader的特点:
- 支持链式传递
- 可以使同步的,也可以异步
- loader运行在Node.js中
- loader能够使用
options
对象进行配置 - 插件plugins可以喂loader带来更多的特性
- loader可以产生额外的任意文件
6.插件 plugins
插件的目的是解决loaders无法实现的其他事
插件是一个具有 apply
属性的js对象, apply
属性会被 webpack compiler调用,并且compiler对象可在整个编译生命周期访问
const pluginName = 'ConsoleLogOnBuildWebpackPlugin';
class ConsoleLogOnBuildWebpackPlugin {
apply(compiler) {
// tap方法的第一个参数应该用用驼峰式命名的插件名称,建议使用一个常量
compiler.hooks.run.tap(pluginName, compilation => {
console.log('webpack 构建过程开始');
})
}
}
用法,插件可以携带 参数/选项(arguments/options),在webpack配置中使用插件需要实例化插件:
const HtmlWebpackPlugin = require('html-webpack-plugin');
const webpack = require('webpack'); // 使用内置的插件
const path = require('path');
const config = {
entry: './path/to/my/entry/file.js',
output: {
filename: 'my-webpack.bundle.js',
path: path.resolve(__dirname, 'dist'),
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
use: 'babel-loader',
},
],
},
plugins: [
new webpack.optimize.UglifyJsPlugin(),
new HtmlWebpackPlugin({ template: './src/index.html' }),
],
};
7.模块 modules
在模块化编程中,开发者将程序分解成你上功能块(discrete chunks of functionality),这称之为模块。
webpack支持的模块:
- ES2015
import
语句 - CommonJS
require()
语句 - AMD
define
和require
语句 - css/sass/less文件中的
@import
语句 - 样式(
url(...)
) 或者 HTML文件(<img src=...>
)中的图片链接
webpack通过加载器可以支持各种语言和预编译器编写模块。加载器描述了如何处理非js文件模块,并且在bundle 中引入这些依赖
8.构建目标 targets
因为服务器和浏览器都可以使用JS编写,所以webpack提供了多种构建目标,可以使用 target
属性设置
// 编译为类Node.js环境,使用Node.js的require
module.exports = {
target: 'node',
};
// 多个Target
// webpack不支持向 target 传入多个字符串
// 但是可以打包2份分离的配置来参加同构的库
let path = require('path');
let serverConfig = {
target: 'node',
output: {
filename: 'lib.node.js',
path: path.resolve(__dirname, 'dist'),
},
};
let clientConfig = {
target: 'web', // 默认是 'web', 可省略这个字段
output: {
filename: 'lib.js',
path: path.resolve(__dirname, 'dist'),
},
};
网友评论