Open ohnowho opened 5 years ago
Gulp 本质是 task runner,Webpack 是 module bundler 我认为 Gulp 正如他的定义一样:基于流的自动化构建工具,定义每一个任务,然后自动将一个个任务执行。 而 webpack 是模块化地组织,模块化地依赖,然后模块化地打包。相对来上,场景局限在前端模块化打包上。
webpack-cli npm install webpack webpack-cli --save-dev webpack 4 把核心代码和客户端分离开了,现在需要安装一个 webpack-cli 才可以启动 webpack 命令。
配置项 - resolve(解析)
取消了 extensions 空字符串(表示导入文件无后缀名)
Webpack1
resolve: {
extensions: ['', '.js', '.css'],
modulesDirectories: ['node_modules', 'src']
}
Webpack2
resolve: {
extensions: ['.js', '.css'],
modules: [
path.resolve(__dirname, 'node_modules'),
path.join(__dirname, './src')
]
}
配置项 - module(模块)
外层 loaders 改为 rules 内层 loader 改为 use 所有插件必须加上 -loader,不再允许缩写 不再支持使用!连接插件,改为数组形式
json-loader 模块移除,不再需要手动添加,webpack2 会自动处理
Webpack1
module: {
loaders: [{
test: /\.(less|css)$/,
loader: "style!css!less!postcss"
}, {
test: /\.json$/,
loader: 'json'
}]
}
Webpack2
module: {
rules: [{
test: /\.(less|css)$/,
use: [
"style-loader",
"css-loader",
"less-loader",
"postcss-loader"
]
}]
};
配置项 - plugins(插件)
移除了 OccurenceOrderPlugin 模块(已内置)、NoErrorsPlugin 模块(已内置)
2 3 两个版本几乎完全兼容,新增部分新特性
加入 Scope Hoisting(作用域提升)
之前版本将每个依赖都分别封装在一个闭包函数中来独立作用域。这些包装函数闭包函数降低了浏览器 JS 引擎解析速度 Webpack 团队参考 Closure Compiler 和 Rollup JS,将有联系的模块放到同一闭包函数中,从而减少闭包函数数量,使文件大小的少量精简,提高 JS 执行效率 在 Webpack3 配置中加入 ModuleConcatenationPlugin 插件来启用作用域提升
module.exports = { plugins: [ new webpack.optimize.ModuleConcatenationPlugin() ] };
加入 Magic Comments(魔法注解)
在 Webpack2 中引入了 Code Splitting-Async 的新方法 import(),用于动态引入 ES Module,Webpack 将传入 import 方法的模块打包到一个单独的代码块(chunk),但是却不能像 require.ensure 一样,为生成的 chunk 指定 chunkName。因此在 Webpack3 中提出了 Magic Comment 用于解决该问题
import(/ webpackChunkName: "my-chunk-name" / 'module');
webpac 4 是一个大版本,其中 plugin 机制都变化挺大的,几乎所有的 plugin 都需要升级来做兼容,这里简单记录一下遇到的一些问题。
零配置:Webpack 4 不需要配置文件,这是 Webpack 4 的一个全新的变更。
性能提升:Webpack 4 是迄今为止最快的 Webpack 版本。
合理的默认值:Webpack 4 的主要概念包括入口、输出、加载器和插件。
webpack 4 把核心代码和客户端分离开了,现在需要安装一个 webpack-cli 才可以启动 webpack 命令。 npm i webpack-cli --save-dev
html-webpack-plugin 要升级到 3.0.6 以上即可。
module.loaders 替换为 modules.rules
module: {
loaders: [
...
]
}
替换为:
module: {
rules: [
...
]
}
extract-text-webpack-plugin 暂不支持 webpack 4,我们可以使用另外一个插件 mini-css-extract-plugin 来替换之。
举个栗子(顺便支持一下 less):
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
...
optimization: {
minimizer: [
new UglifyJsPlugin({ cache: true, parallel: true, sourceMap: false }),
new OptimizeCSSAssetsPlugin({})
]
},
plugins: [
new MiniCssExtractPlugin({ filename: 'css/index.css' }),
],
...
module: {
rules: [
{
test: /\.less$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader']
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader']
},
]
}
webpack 4 增加了一个 mode 配置,值可选有两个 development 和 production,对不同的环境他会提供不同的一些默认配置,比如开发环境下默认开启 optimization.namedModules(原NamedModulesPlugin,现已弃用),而生产环境默认使用 `optimization.noEmitOnErrors(原NoEmitOnErrorsPlugin,现已弃用)。
不同模式下的默认配置:
生产环境默认开启了很多代码优化(minify,splite 等)
开发时开启注视和验证,并且自动加上了 eval devtool
生产环境不支持 watching,开发环境优化了重新打包的速度
生产环境开启模块串联(原 ModuleConcatenationPlugin),没用过不多说
自动设置 process.env.NODE_ENV 到不同环境,也就是不需要 DefinePlugin 来做这个了
如果你给 mode 设置为 none,所有默认配置都去掉了
CommonsChunkPlugin删除之后,改成使用optimization.splitChunks进行模块划分,详细文档看 这里。
官方的说法是默认设置已经对大部分用户来说非常棒了,但是需要注意一个问题,默认配置只会对异步请求的模块进行提取拆分,如果要对 entry 进行拆分,需要设置 optimization.splitChunks.chunks = 'all'。
对应之前我们拆分runtime的情况,现在也有一个配置optimization.runtimeChunk,设置为true就会自动拆分runtime文件。
真实例子 webpack.conf.js
'use strict';
const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin'); // Html文件处理
module.exports = {
entry: {
index: './src/index.js'
},
output: {
path: path.resolve(__dirname, './build'), // This is where images AND js will go
publicPath: '', // This is used to generate URLs to e.g. images
filename: 'js/[name].js',
chunkFilename: 'js/[id].chunk.js?[hash:8]'
},
mode: 'development', // 'production'
optimization: {
minimizer: [
new UglifyJsPlugin({ cache: true, parallel: true, sourceMap: false }),
new OptimizeCSSAssetsPlugin({})
]
},
plugins: [
// 单独打包CSS
new MiniCssExtractPlugin({ filename: 'css/index.css' }),
new CopyWebpackPlugin([
{ from: 'src/images/*', to: 'images/', flatten: true},
{ from: 'src/parallax/*', to: 'js/', flatten: true}
], {}),
new HtmlWebpackPlugin({
filename: 'index.html',
chunks: ['index'],
template: './src/index.html',
hash: true
})
],
module: {
rules: [
{
test: /\.js$/,
loader: 'babel-loader', // ES6
exclude: /(node_modules|parallax|fullpage)/
},
// { test: /\.css$/, loader: 'style-loader!css-loader' },
// { test: /\.less$/, loader: 'style-loader!css-loader!less-loader' }, // use ! to chain loaders
{
test: /\.less$/,
use: [MiniCssExtractPlugin.loader, 'css-loader', 'less-loader']
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader']
},
{
test: /\.(png|jpg|gif)$/,
loader: 'url-loader',
query: {
name: '[path][name].[ext]?[hash:8]',
limit: 8192 // inline base64 URLs for <=8k images, direct URLs for the rest
}
}
]
}
};
extract-text-webpack-plugin@2.1.2 requires a peer of webpack@^2.2.0 but none is installed. You must install peer dependencies yourself.
npm WARN webpack-dev-middleware@1.12.2 requires a peer of webpack@^1.0.0 || ^2.0.0 || ^3.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN webpack-dev-server@2.11.2 requires a peer of webpack@^2.2.0 || ^3.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN ajv-errors@1.0.1 requires a peer of ajv@>=5.0.0 but none is installed. You must install peer dependencies yourself.
webpack4,不再支持extract-text-webpack-plugin npm i mini-css-extract-plugin -D npm uninstall extract-text-webpack-plugin -D
npm i webpack-dev-server webpack-dev-middleware -D npm uninstall webpack-dev-server webpack-dev-middleware -D
ajv-errors npm uninstall ajv-errors -D npm i ajv-errors -D
npm install -g npm-install-peers
npm install -g npm npm i ajv
Module not found: Error: Can't resolve 'file' in 'E:\workspace\kae-doc\public'
BREAKING CHANGE: It's no longer allowed to omit the '-loader' suffix when using loaders.
You need to specify 'file-loader' instead of 'file',
npm i file-loader -D loader: 'file', 改为 loader: 'file-loader',
一部分图片可以用 一部分不可以 因为 url-loader 和file-loader处理不同
TypeError: Cannot read property 'bindings' of null
npm install --save-dev @babel/cli @babel/core @babel/preset-env npm uninstall -D babel-loader babel-core babel-preset-env
icon乱码
输出文件加上hash 用于区别
webpack各个版本比较
Gulp 本质是 task runner,Webpack 是 module bundler 我认为 Gulp 正如他的定义一样:基于流的自动化构建工具,定义每一个任务,然后自动将一个个任务执行。 而 webpack 是模块化地组织,模块化地依赖,然后模块化地打包。相对来上,场景局限在前端模块化打包上。
webpack-cli npm install webpack webpack-cli --save-dev webpack 4 把核心代码和客户端分离开了,现在需要安装一个 webpack-cli 才可以启动 webpack 命令。
webpack 1
webpack2
5. 配置选项语法有较大改动,且不向下兼容
配置项 - resolve(解析)
取消了 extensions 空字符串(表示导入文件无后缀名)
配置项 - module(模块)
外层 loaders 改为 rules 内层 loader 改为 use 所有插件必须加上 -loader,不再允许缩写 不再支持使用!连接插件,改为数组形式
json-loader 模块移除,不再需要手动添加,webpack2 会自动处理
配置项 - plugins(插件)
移除了 OccurenceOrderPlugin 模块(已内置)、NoErrorsPlugin 模块(已内置)
webpack 3
2 3 两个版本几乎完全兼容,新增部分新特性
加入 Scope Hoisting(作用域提升)
之前版本将每个依赖都分别封装在一个闭包函数中来独立作用域。这些包装函数闭包函数降低了浏览器 JS 引擎解析速度 Webpack 团队参考 Closure Compiler 和 Rollup JS,将有联系的模块放到同一闭包函数中,从而减少闭包函数数量,使文件大小的少量精简,提高 JS 执行效率 在 Webpack3 配置中加入 ModuleConcatenationPlugin 插件来启用作用域提升
module.exports = { plugins: [ new webpack.optimize.ModuleConcatenationPlugin() ] };
加入 Magic Comments(魔法注解)
在 Webpack2 中引入了 Code Splitting-Async 的新方法 import(),用于动态引入 ES Module,Webpack 将传入 import 方法的模块打包到一个单独的代码块(chunk),但是却不能像 require.ensure 一样,为生成的 chunk 指定 chunkName。因此在 Webpack3 中提出了 Magic Comment 用于解决该问题
import(/ webpackChunkName: "my-chunk-name" / 'module');
webpack4
webpac 4 是一个大版本,其中 plugin 机制都变化挺大的,几乎所有的 plugin 都需要升级来做兼容,这里简单记录一下遇到的一些问题。
零配置:Webpack 4 不需要配置文件,这是 Webpack 4 的一个全新的变更。
性能提升:Webpack 4 是迄今为止最快的 Webpack 版本。
合理的默认值:Webpack 4 的主要概念包括入口、输出、加载器和插件。
webpack 4 把核心代码和客户端分离开了,现在需要安装一个 webpack-cli 才可以启动 webpack 命令。 npm i webpack-cli --save-dev
html-webpack-plugin 要升级到 3.0.6 以上即可。
module.loaders 替换为 modules.rules
extract-text-webpack-plugin 暂不支持 webpack 4,我们可以使用另外一个插件 mini-css-extract-plugin 来替换之。
webpack 4 增加了一个 mode 配置,值可选有两个 development 和 production,对不同的环境他会提供不同的一些默认配置,比如开发环境下默认开启 optimization.namedModules(原NamedModulesPlugin,现已弃用),而生产环境默认使用 `optimization.noEmitOnErrors(原NoEmitOnErrorsPlugin,现已弃用)。
不同模式下的默认配置:
CommonsChunkPlugin删除之后,改成使用optimization.splitChunks进行模块划分,详细文档看 这里。
官方的说法是默认设置已经对大部分用户来说非常棒了,但是需要注意一个问题,默认配置只会对异步请求的模块进行提取拆分,如果要对 entry 进行拆分,需要设置 optimization.splitChunks.chunks = 'all'。
对应之前我们拆分runtime的情况,现在也有一个配置optimization.runtimeChunk,设置为true就会自动拆分runtime文件。
问题总结
extract-text-webpack-plugin
webpack4,不再支持extract-text-webpack-plugin npm i mini-css-extract-plugin -D npm uninstall extract-text-webpack-plugin -D
npm i webpack-dev-server webpack-dev-middleware -D npm uninstall webpack-dev-server webpack-dev-middleware -D
ajv-errors npm uninstall ajv-errors -D npm i ajv-errors -D
npm install -g npm-install-peers
npm install -g npm npm i ajv
file-loader
npm i file-loader -D loader: 'file', 改为 loader: 'file-loader',
部分图片不可用
一部分图片可以用 一部分不可以 因为 url-loader 和file-loader处理不同
babel-cli
npm install --save-dev @babel/cli @babel/core @babel/preset-env npm uninstall -D babel-loader babel-core babel-preset-env
baggyui 和 chopperui同时在一个项目中引用
打包原理
webpack.config.js
文件输入输出
module
resolve
resolve.root与resolve.modules 配置根路径 resolve.root在webpack v1版本中使用,而在webpack v2 中,使用modules代替,建议使用v2版
当vue是最后一级路径时,webpack才会将该值解析成别名,进行别名与对应值替换,如vue/test.js中的vue是不会当作别名解析的
plugins
对你的项目webpack模块构建过程进行额外处理,如代码压缩,图片等资源提交压缩,构建异常捕获和提升,构建流程时间消耗比,等等
babel-polyfill
我们需要明白的一点是babel-preset-es2015能做的,只是转换ES6代码成ES5,使得浏览器可以解析执行,但是对于ES6新提出的API,如Promise,Generator等无法简单的转换成ES5代码,这时就需要babel-polyfill了,babel-polyfill是一个垫片,它可以模拟提供所有的ES6功能和特性,可以看作是提供了一个模拟的全局ES6环境
在webpack.config.js中配置打包入口文件时加入该垫片:
webpack-dev-server
webpack-dev-server是一个Node.js的express服务器,以webpack开发中间件的形式为webpack包提供服务,当监听到源码文件变更时,会自动重新打包,并且支持配置自动刷新浏览器,重新加载资源。
开启webpack-dev-server后,变更文件重新打包后,并不会实际输出到配置的output目录,而是在publicPath属性声明的相对路径所在的内存中读取
参考链接
打包原理