webpack
配置
entry
- 整个项目工程文件的入口点
- entry: { app: path.resolve(__dirname, 'src/index.js') },
- 多个入口
- entry: { admin: './admin/index.js', consumer: './consumer/index.js' },
- 默认值为 ./src
-
分离 应用程序(app) 和 第三方库(vendor) 入口
- const config = { entry: { app: './src/app.js', vendors: './src/vendors.js' } };
output
- const config = { entry: { app: './src/app.js', vendors: './src/vendors.js' } };
-
解析编译后生成压缩文件路径,以及如何命名这些文件
- output: { publicPath: '/', filename: 'public/js/[name].[hash:8].js', path: path.resolve(__dirname, 'dist') },
- 默认值为 ./dist
- path.resolve是nodeJs里面的方法,可以连接两个相对路径并生成绝对路径
- path与publicPath
- path:打包后文件在硬盘中的存储位置。
- publicPath:打包后浏览器访问服务时的 url 路径(中通用的一部分)
- publicPath可用于改css中资源请求路径。
- filename
- "bundle.js", // string
- "[name].js", // 用于多个入口点(entry point)(出口点?)
- "[chunkhash].js", // 用于长效缓存
-
library
- "MyLibrary" // 导出库(exported library)的名称
module
- "MyLibrary" // 导出库(exported library)的名称
-
主要定义项目中的解析器例如css, jsx, babel等等
- rules
- { test: /.jsx?$/, include: [ path.resolve(_dirname, "app") ], exclude: [ path.resolve(_dirname, "app/demo-files") ], loader: "babel-loader", },
- 每个选项都接收一个正则表达式或字符串
- test 和 include 具有相同的作用,都是必须匹配选项
- exclude 是必不匹配选项(优先于 test 和 include)
- 最佳实践:
- 只在 test 和 文件名匹配 中使用正则表达式
- 在 include 和 exclude 中使用绝对路径数组
- 尽量避免 exclude,更倾向于使用 include
-
loader
- 让 webpack 能够去处理那些非 JavaScript 文件(webpack 自身只理解 JavaScript),loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块,然后就可以利用 webpack 的打包能力,对它们进行处理。
- npm安装加载
- 属性
- test
- 用于标识出应该被对应的 loader 进行转换的某个或某些文件
- use
- 表示进行转换时,应该使用哪个 loader
- test
- 常用
- 预处理
- css-loader 处理css中路径引用等问题
- style-loader 动态把样式写入css
- sass-loader scss编译器
- less-loader less编译器
- postcss-loader scss再处理
- js处理
- babel-loader
- jsx-loader
- image-loader
- url-loader
- 预处理
- ”-loader”可以省略不写,多个loader之间用“!”连接起来
- loaders: [ { test: /.css$/, loader: 'style-loader!css-loader' }, { test: /.scss$/, loader: 'style!css!sass?sourceMap'}, ]
mode
- loaders: [ { test: /.css$/, loader: 'style-loader!css-loader' }, { test: /.scss$/, loader: 'style!css!sass?sourceMap'}, ]
-
通过选择 development 或 production 之中的一个,来设置 mode 参数
- module.exports = { mode: 'production' };
- development
- 会将 process.env.NODE_ENV 的值设为 development。启用 NamedChunksPlugin 和 NamedModulesPlugin。
- production
- 会将 process.env.NODE_ENV 的值设为 production。启用 FlagDependencyUsagePlugin, FlagIncludedChunksPlugin, ModuleConcatenationPlugin, NoEmitOnErrorsPlugin, OccurrenceOrderPlugin, SideEffectsFlagPlugin 和 UglifyJsPlugin.
-
none
plugin
-
插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量。插件接口功能极其强大,可以用来处理各种各样的任务。
- new HtmlWebpackPlugin
- 单独生成html文件
- new BrowserSyncPlugin
- 使用browser-sync实时刷新页面
- new webpack.optimize.UglifyJsPlugin
- 负责压缩JS代码,并控制是否要显示警告
- new webpack.optimize.DedupePlugin
- 主要查找相等或近似的模块,避免在最终生成的文件中出现重复的模块,比如可以用它去除依赖中重复的插件。
- new webpack.optimize.OccurenceOrderPlugin
- 这个插件为组件和模块分配ID,通过这个插件webpack可以分析和优先考虑使用最多的模块,并为它们分配最小的ID,通过分析ID,可以建议降低总文件的大小。
- new webpack.HotModuleReplacementPlugin
- 全局开启代码热替换,
-
new ExtractTextPlugin
- 默认情况下,css是被打包到js中的如果接受不了,我们可以应用这个plugin将css style提取出来。
resolve
- 默认情况下,css是被打包到js中的如果接受不了,我们可以应用这个plugin将css style提取出来。
-
其他解决方案
- module
- 用于查找模块的目录
- modules: [ "node_modules", path.resolve(__dirname, "app") ],
- 用于查找模块的目录
- extensions
- 使用的扩展名
- extensions: [".js", ".json", ".jsx", ".css"],
- 使用的扩展名
-
alias
- 模块别名列表
- alias: { "module": "new-module", // 起别名:"module" -> "new-module" 和 "module/path/file" -> "new-module/path/file" "module": path.resolve(__dirname, "app/third/module.js"), // 起别名 "module" -> "./app/third/module.js" 和 "module/file" 会导致错误 // 模块别名相对于当前上下文导入 },
context
- alias: { "module": "new-module", // 起别名:"module" -> "new-module" 和 "module/path/file" -> "new-module/path/file" "module": path.resolve(__dirname, "app/third/module.js"), // 起别名 "module" -> "./app/third/module.js" 和 "module/file" 会导致错误 // 模块别名相对于当前上下文导入 },
- 模块别名列表
-
__dirname, // string(绝对路径!)
-
webpack 的主目录,entry 和 module.rules.loader 选项相对于此目录解析
externals
-
["react", /^@angular\//]
- 不要遵循/打包这些模块,而是在运行时从环境中请求他们
多种配置导出类型
函数
-
module.exports = function(env, argv) { return { mode: env.production ? 'production' : 'development', devtool: env.production ? 'source-maps' : 'eval', plugins: [ new webpack.optimize.UglifyJsPlugin({ compress: argv['optimize-minimize'] // 只有传入 -p 或 --optimize-minimize }) ] }; };
promise
-
module.exports = () => { return new Promise((resolve, reject) => { setTimeout(() => { resolve({ entry: './app.js', /* ... */ }) }, 5000) }) }
-
webpack 将运行由配置文件导出的函数,并且等待 Promise 返回。便于需要异步地加载所需的配置变量。
多个配置对象
-
导出多个配置对象,对于针对多个构建目标(例如 AMD 和 CommonJS)打包一个 library 非常有用。
- module.exports = [{ output: { filename: './dist-amd.js', libraryTarget: 'amd' }, entry: './app.js', mode: 'production', }, { output: { filename: './dist-commonjs.js', libraryTarget: 'commonjs' }, entry: './app.js', mode: 'production', }]
优势
以 commonJS 的形式书写脚本,但对 AMD/CMD 的支持也很全面,方便旧项目进行代码迁移。
能被模块化的不仅仅是 JS
开发便捷,能替代部分 grunt/gulp 的工作,比如打包、压缩混淆、图片转base64等
扩展性强,插件机制完善,特别是支持 React 热插拔(见 react-hot-loader )
安装
npm install webpack –save-dev
npm install webpack −g
把依赖写入package.json包: npm init
运行
webpack
webpack –display-error-details
- 出错时能查阅更详尽的信息
webpack.config.js文件解析:
1 const path = require('path'); 2 const webpack = require('webpack'); 3 const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 const CleanWebpackPlugin = require('clean-webpack-plugin'); 5 const MiniCssExtractPlugin = require('mini-css-extract-plugin'); 6 const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); 7 const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin'); 8 const config = require('./config'); 9 const theme = require('./theme'); 10 11 const { API_ENV } = process.env; 12 const BASE_URL = config.domains[API_ENV].default; 13 14 module.exports = { 15 entry: { // 工程入口 16 app: path.resolve(__dirname, 'src/index.js') // __dirname当前目录 17 }, 18 mode: 'development', // 模式-开发模式 19 devtool: 'cheap-module-eval-source-map', // 是否以及如何生成源映射。影响build和rebuild速度。 20 devServer: { 21 contentBase: './dist', // 告诉服务器从哪里提供内容 22 hot: true, // 启用webpack的热模块替换功能 23 port: 8000, // 指定用于侦听请求的端口号 24 host:'0.0.0.0', // 指定要使用的主机。默认情况下这是localhost。 25 historyApiFallback: true, // 使用HTML5历史记录API时,index.html可能必须提供该页面以代替任何404回复。通过传递启用此功能 26 proxy: { // 代理 当拥有单独的API后端开发服务器并且希望在同一域上发送API请求时,代理某些URL会很有用 27 "/api": { 28 target: BASE_URL, // 在后端打开的情况下启用代理BASE_URL 29 changeOrigin: true, 30 pathRewrite: { // 不想/api传递,重写路径 31 "^/api": "" 32 } 33 } 34 }, 35 inline: true // 实时刷新 36 }, 37 output: { // 混淆压缩后的文件输出 38 publicPath: '/', // 39 filename: 'public/js/[name].[hash:8].js', // 文件名 40 path: path.resolve(__dirname, 'dist') // 文件位置路径 41 }, 42 optimization: { 43 // 分离公共依赖块打包文件 44 splitChunks: { 45 chunks: 'all' 46 } 47 }, 48 plugins: [ // 插件 49 new HtmlWebpackPlugin({ // 单独生成HTML文件 50 template: path.resolve(__dirname, 'public/index.html'), // src文件 51 filename: 'index.html'// dist文件 52 }), 53 new webpack.HotModuleReplacementPlugin() 54 ], 55 module: { // 主要定义项目中的解析器例如css, jsx, babel等等,使用loader 56 rules: [ 57 { 58 test: /\.(js|jsx)$/, // 被打包文件-后缀名为js或jsx的文件 59 loader: 'babel-loader?cacheDirectory', // 使用babel-loader打包 60 include: [ 61 path.resolve(__dirname, './src/') 62 ], 63 exclude: /node_modules/, 64 options: { 65 plugins: [ 66 [ 67 'import', 68 { 69 libraryName: 'antd-mobile', 70 style: true 71 }, 72 'react-photoswipe' 73 ], 74 'transform-decorators-legacy' 75 ] 76 } 77 }, 78 { 79 test: /\.(css|less)$/, 80 exclude: /node_modules/, 81 use: [ // 对test文件打包之前,先用以下loader转换文件 82 { 83 loader:'style-loader' 84 }, 85 { 86 loader: 'css-loader', 87 options: { 88 sourceMap: true, 89 modules: true, 90 localIdentName: "[local]--[hash:base64:5]" 91 } 92 }, 93 { 94 loader: 'less-loader', 95 options: { 96 javascriptEnabled: true, 97 modifyVars: theme 98 } 99 } 100 ] 101 }, 102 { 103 test: /\.(css|less)$/, 104 include: /node_modules/, 105 use: [ 106 { 107 loader:'style-loader' 108 }, 109 { 110 loader: 'css-loader' 111 }, 112 { 113 loader: 'less-loader', 114 options: { 115 javascriptEnabled: true, 116 modifyVars: theme 117 } 118 } 119 ] 120 }, 121 { 122 test: /\.(png|svg|jpe?g|gif)$/i, 123 exclude: /node_modules/, 124 use: [ 125 { 126 loader: 'file-loader', 127 options: { 128 outputPath: 'public/images/', 129 name: '[name].[hash:8].[ext]' 130 } 131 } 154 ] 155 }, 156 { 157 test: /\.(woff|woff2|eot|ttf|otf)$/, 158 exclude: /node_modules/, 159 use: [ 160 'file-loader' 161 ] 162 } 163 ] 164 }, 165 resolve: { 166 alias: { // 依赖 对引用的文件设置别名 167 assets: path.resolve(__dirname, 'src/assets'), 168 images: path.resolve(__dirname, 'src/assets/images'), 169 utils: path.resolve(__dirname, 'src/utils'), 170 pages: path.resolve(__dirname, 'src/pages'), 171 components: path.resolve(__dirname, 'src/components') 172 } 173 } 174 };