Open chaims opened 7 years ago
const path = require('path');
const webpack = require('webpack');
module.exports = {
context: path.resolve(__dirname, './src'),
entry: {
app: ['./home.js', './events.js', './vendor.js'],
},
output: {
path: path.resolve(__dirname, './dist'),
filename: '[name].bundle.js',
},
};
自动打包第三方库
new webpack.optimize.CommonsChunkPlugin({
name:'commons',
filename:'commons.js',
minChunks:2
})
如果有任意模块加载了两次或更多(通过 minChunks 设置该值),它就会被打包进一个叫 commons.js 的文件里,后面你就可以在客户端缓存这个文件了。
手动打包第三方库
module.exports = {
entry: {
index: './index.js',
vendor: ['react', 'react-dom', 'rxjs'],
},
......
}
webpack -v
webpack -p
webpack --optimize-minimize --define process.env.NODE_ENV="'production'"
使用UglifyJsPlugin进行 JS文件压缩;
运行LoaderOptionsPlugin; 帮助人们从 webpack 1 迁移至 webpack 2,webpack 2 中对 webpack.config.js 的结构要求变得更加严格;不再开放扩展给其他的加载器/插件。
设置Node环境变量;
指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。
module.exports = {
entry: './path/to/my/entry/file.js'
};
告诉 webpack 在哪里输出它所创建的 bundles
,以及如何命名这些文件,主输出文件默认为 ./dist/main.js
,其他生成文件的默认输出目录是./dist
const path = require('path');
module.exports = { entry: './path/to/my/entry/file.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'my-first-webpack.bundle.js' } };
- output.filename: webpack bundle 的名称
- output.path: bundle 生成(emit)到哪里
### loader
loader 能够 import 导入任何类型的模块(例如 .css 文件),并且先将它们转换为有效 模块,然后添加到依赖图中。
const path = require('path'); module.exports = { output: { filename: 'my-first-webpack.bundle.js' }, module: { rules: [ { test: /.txt$/, use: 'raw-loader' } ] } };
- test 属性,用于标识出应该被对应的 loader 进行转换的某个或某些文件。
- use 属性,表示进行转换时,应该使用哪个 loader。
> [loader](https://webpack.docschina.org/concepts/loaders)
### 插件(plugins)
loader 被用于转换某些类型的模块,而插件则可以用于执行范围更广的任务,插件的范围包括:打包优化、资源管理和注入环境变量。
想要使用一个插件,你只需要 require() 它,然后把它添加到 plugins 数组中。
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 通过 npm 安装 const webpack = require('webpack'); // 用于访问内置插件
module.exports = { module: { rules: [ { test: /.txt$/, use: 'raw-loader' } ] }, plugins: [ new HtmlWebpackPlugin({template: './src/index.html'}) ] };
> [插件列表](https://webpack.docschina.org/plugins)
### 模式
通过将```mode```参数设置为```development, production 或 none```,可以启用对应环境下 webpack 内置的优化。默认值为```production```。
module.exports = { mode: 'production' };
或者
webpack --mode=production
### 资料
- [手动打包一个应用程序](https://www.youtube.com/watch?v=UNMkLHzofQI)
- [实时编写一个简单的模块打包工具](https://www.youtube.com/watch?v=Gc9-7PBqOC8)
- [简单模块打包工具的细节说明](https://github.com/ronami/minipack)
mkdir webpack-demo && cd webpack-demo
npm init -y
npm install webpack webpack-cli --save-dev
使用一个配置文件
webpack-demo
|- package.json
+ |- webpack.config.js
|- /dist
|- index.html
|- /src
|- index.js
webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist')
}
};
执行
npx webpack --config webpack.config.js
NPM 脚本
{
"name": "webpack-demo",
"version": "1.0.0",
"description": "",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
+ "build": "webpack"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^4.0.1",
"webpack-cli": "^2.0.9",
"lodash": "^4.17.5"
}
}
执行
npm run build
在 module 配置中 安装并添加 style-loader 和 css-loader
npm install --save-dev style-loader css-loader
webpack.config.js
+ module: {
+ rules: [
+ {
+ test: /\.css$/,
+ use: [
+ 'style-loader',
+ 'css-loader'
+ ]
+ }
+ ]
+ }
index.js
import './style.css';
......
使用 file-loader,我们可以轻松地将这些内容混合到 CSS 中:
npm install --save-dev file-loader
webpack.config.js
+ {
+ test: /\.(png|svg|jpg|gif)$/,
+ use: [
+ 'file-loader'
+ ]
+ }
当使用 css-loader 时,CSS 中的 url('./my-image.png') 会使用类似的过程去处理;
html-loader
以相同的方式处理<img src="./my-image.png" />
。压缩和优化图像查看
image-webpack-loader 和 url-loader
了解更多关于增强加载处理图片功能。
file-loader 和 url-loader 可以接收并加载任何文件,然后将其输出到构建目录,同图片处理
加载的有用资源还有数据,如 JSON 文件,CSV、TSV 和 XML,要导入 CSV、TSV 和 XML,你可以使用 csv-loader
和 xml-loader
以以上的方式加载资源,你可以以更直观的方式将模块和资源组合在一起,使你的代码更具备可移植性,类似下面的结构:
- |- /assets
+ |– /components
+ | |– /my-component
+ | | |– index.jsx
+ | | |– index.css
+ | | |– icon.svg
+ | | |– img.png
见上面 output章节
+ entry: { + app: './src/index.js', + print: './src/print.js' + }, output: { + filename: '[name].bundle.js', path: path.resolve(__dirname, 'dist') }
HtmlWebpackPlugin
HtmlWebpackPlugin 默认生成 index.html 文件
+ plugins: [ + new HtmlWebpackPlugin({ + title: 'Output Management' + }) + ],
清理 /dist 文件夹
new CleanWebpackPlugin(['dist'])
Manifest
TODO
为了更容易地追踪错误和警告,JavaScript 提供了 source map 功能,将编译后的代码映射回原始源代码。 source map 有很多不同的选项可用:
webpack 中有几个不同的选项,可以帮助你在代码发生变化后自动编译代码:
webpack's Watch Mode 实时看到修改后的实际效果,需要刷新浏览器
"scripts": {
"watch": "webpack --watch", }
webpack-dev-server 能够实时重新加载 webpack.config.js
devServer: {
contentBase: './dist'
},
package.json
"scripts": { "watch": "webpack --watch",
"start": "webpack-dev-server --open" },
webpack-dev-middleware webpack-dev-middleware 是一个容器(wrapper),它可以把 webpack 处理后的文件传递给一个服务器(server)
HMR 不适用于生产环境,应当只在开发环境使用
启用 HMR
+ const webpack = require('webpack'); devServer: { contentBase: './dist', + hot: true }, plugins: [ ... + new webpack.HotModuleReplacementPlugin() ],
当使用 webpack dev server 和 Node.js API 时,不要将 dev server 选项放在 webpack 配置对象中,而是,在创建选项时,将其作为第二个参数传递
new WebpackDevServer(compiler, options)
addDevServerEntrypoints
移除 JavaScript 上下文中的未引用代码。
将文件标记为无副作用,简单地将该属性标记为 false,来告知 webpack,它可以安全地删除未用到的 export 导出。 pack.json
{
"name": "your-project",
"sideEffects": false
}
{
"name": "your-project",
"sideEffects": [
"./src/some-side-effectful-file.js",
"*.css"
]
}
从 webpack 4 开始,也可以通过 "mode" 配置选项轻松切换到压缩输出,只需设置为 "production"。
也可以在命令行接口中使用 --optimize-minimize
标记,来启用 UglifyJSPlugin。
使用 tree shaking,你必须:
使用 ES2015 模块语法(即 import 和 export)。
在项目 package.json 文件中,添加一个 "sideEffects" 属性。
引入一个能够删除未引用代码(dead code)的压缩工具(minifier)(例如 UglifyJSPlugin)。
通常建议为每个环境编写彼此独立的 webpack 配置。 webpack-merge
+ const merge = require('webpack-merge');
+ const common = require('./webpack.common.js');
+
+ module.exports = merge(common, {
+ mode: 'production',
+ });
生产环境中一般使用 source-map
选项,在开发环境中用到的 inline-source-map
使用 webpack 内置的 DefinePlugin 为所有的依赖定义这个变量
const webpack = require('webpack'); const merge = require('webpack-merge'); const UglifyJSPlugin = require('uglifyjs-webpack-plugin'); const common = require('./webpack.common.js');
module.exports = merge(common, { mode: 'production', devtool: 'source-map', plugins: [
> 注意: 任何位于 /src 的本地代码都可以关联到 process.env.NODE_ENV 环境变量
src/index.js
import { cube } from './math.js';
+
+ if (process.env.NODE_ENV !== 'production') {
+ console.log('Looks like we are in development mode!');
+ }
--optimize-minimize
标记将在后台引用 UglifyJSPlugin
--define process.env.NODE_ENV="'production'"
把代码分离到不同的 bundle 中,然后可以按需加载或并行加载这些文件,有以下几种方法:
最简单、最直观的分离代码的方式,这种方式手动配置较多,并有一些陷阱。
entry: {
index: './src/index.js',
**问题**
SplitChunksPlugin SplitChunks 插件可以将公共的依赖模块提取到已有的入口 chunk 中,或者提取到一个新生成的 chunk。
+ optimization: {
+ splitChunks: {
+ chunks: 'all'
+ }
+ }
一些对于代码分离很有帮助的插件和 loaders
mini-css-extract-plugin: 用于将 CSS 从主应用程序中分离。
bundle-loader: 用于分离代码和延迟加载生成的 bundle。
promise-loader: 类似于 bundle-loader ,但是使用的是 promises。
当涉及到动态代码拆分时,webpack 提供了两个类似的技术:
官方分析工具:
打包library,能够实现以下几个目标:
此外,用户应该能够通过以下方式访问 library:
更倾向于把 lodash 当作 peerDependency,放弃对外部 library 的控制,而是将控制权让给使用 library 的用户
+ externals: {
+ lodash: {
+ commonjs: 'lodash',
+ commonjs2: 'lodash',
+ amd: 'lodash',
+ root: '_'
+ }
+ }
对于从一个依赖目录中,调用多个文件的 library,需要逐个排除它们,或者使用正则表达式排除:
externals: [
'library/one',
'library/two',
// 所有以 "library/" 开始的
/^library\/.+$/
]
我们希望能够兼容不同的环境,例如 CommonJS,AMD,Node.js 或者作为一个全局变量。为了让 library 能够在各种用户环境(consumption)中可用,需要在 output 中添加 library 属性:
output: {
path: path.resolve(__dirname, 'dist'),
+ filename: 'webpack-numbers.js',
+ library: 'webpackNumbers',
+ libraryTarget: 'umd'
},
当 import 引入模块时,可以将 library bundle 暴露为名为 webpackNumbers 的全局变量。为了让 library 和其他环境兼容,还需要在配置文件中添加 libraryTarget 属性。这是可以控制 library 如何以不同方式暴露的选项。
暴露 library的方式:
如果设置了 library 但没设置 libraryTarget,则 libraryTarget 默认为 var
最终步骤
通过设置 package.json 中的 main 字段,添加生成 bundle 的文件路径:
{ ... "main": "dist/webpack-numbers.js", ... }
或
{ ... "module": "src/index.js", ... }
目录
创建library
webpack
优势:
目标:
安装
当然如果常规项目还是把依赖写入 package.json 包去更人性化: