Open HolyZheng opened 6 years ago
接触的时候已经到了webpack4版本。webpack4的改变:参考dwqs同学的webpack4不完全指南
webpack中的关键概念
/** webpack.production.config.js **/
// webpack 2/3
module.exports = {
plugins: [
new UglifyJsPlugin(/* ... */),
new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("production") }),
new webpack.optimize.ModuleConcatenationPlugin(),
/*
* 分析出模块之间的依赖关系,尽可能的把打散的模块合并到一个函数中去,但前提是不能造成代码冗
* 余。 因此只有那些被引用了一次的模块才能被合并。
*/
new webpack.NoEmitOnErrorsPlugin()
// 在编译出现错误时,使用它来跳过输出阶段。这样可以确保输出资源不会包含错误。
]
}
// webpack 4
module.exports = {
mode: 'production'
}
/** webpack.development.config.js **/
// webpack 2/3
module.exports = {
plugins: [
new webpack.NamedModulesPlugin(),
// 当开启 HMR 的时候使用该插件会显示模块的相对路径,建议用于开发环境
new webpack.DefinePlugin({ "process.env.NODE_ENV": JSON.stringify("development") })
]
}
// webpack 4
module.exports = {
mode: 'development'
}
允许在运行时更新各种模块,而无需进行完全刷新。
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
// 每次打包创建新的html
const CleanWebpackPlugin = require('clean-webpack-plugin')
// 每次打包先清空dist文件夹
const webpack = require('webpack')
module.exports = {
entry: {
app: './src/index.js'
},
// 追踪错误,仅在开发阶段使用
devtool: 'inline-source-map',
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
title: 'Development'
}),
// new webpack.NamedModulesPlugin(), 生成环境下默认开启
// 以便更容易查看要修补(patch)的依赖
new webpack.HotModuleReplacementPlugin()
// 热替换模块
],
mode: 'development',
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
},
// 将dist目录下的文件作为可访问文件,在package.json中添加script脚本
// "start": "webpack-dev-server --open"
devServer: {
contentBase: './dist',
hot: true
},
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
// style-loader当更新 CSS 依赖模块时,此 loader 在后台使用 module.hot.accept 来修补(patch)
// <style> 标签
}
]
}
}
tree shaking 是一个术语,通常用于描述移除 JavaScript 上下文中的未引用代码(dead-code)。它依赖于 ES2015 模块系统中的静态结构特性,例如 import 和 export。我们需要做的就是将文件标记为无副作用,或者将有副作用的文件标记出来。
{
"name": "your-project",
"sideEffects": false
// 都没有副作用,都可以进行tree shaking
}
{ "name": "your-project", "sideEffects": [ "./src/some-side-effectful-file.js", "*.css" ] // 列出有副作用的文件,避免进行tree shaking }
> ps:副作用」的定义是,在导入时会执行特殊行为的代码,而不是仅仅暴露一个 export 或多个 export。举例说明,例如 polyfill,它影响全局作用域,并且通常不提供 export。
### 3. 生成环境搭建
针对不同的环境,进行不同的配置,用webpage-merge进行合并。
如:
```js
// webpack.common.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const CleanWebpackPlugin = require('clean-webpack-plugin')
module.exports = {
entry: {
app: './src/index.js'
},
plugins: [
new CleanWebpackPlugin(['dist']),
new HtmlWebpackPlugin({
title: 'production'
})
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
}
// webpack.dev.js
const merge = require('webpack-merge')
const common = require('./webpack.common.js')
module.exports = merge(common, {
devtool: 'inline-source-map',
devServer: {
contentBase: './dist'
}
})
// webpack.prod.js
const merge = require('webpack-merge')
const UglifyJSPlugin = require('uglifyjs-webpack-plugin')
const common = require('./webpack.common.js')
const webpack = require('webpack')
module.exports = merge(common, {
devtool: 'source-map',
plugins: [
// new UglifyJSPlugin({
// sourceMap: true
//}),
// 在webpack4的production模式下,webpack.DefinePlugin 插件的
// process.env.NODE_ENV 的值不需要再定义,默认是 production
// new webpack.DefinePlugin({
// 'process.env.NODE_ENV': JSON.stringify('production')
// })
// webpack中需要通过defineplugin来设置process.env.NODE_ENV的值,
// 以便其他的library使用该变量
],
mode: 'production'
})
参考文章:RIP CommonsChunkPlugin
推荐参考翻译:RIP CommonsChunkPlugin翻译
webpack4移除了CommonsChunkPlugin插件,增加了optimization.splitchunks
和optimization.runtimeChunk
配置项,这两个配置项的默认配置已经可以满足大部分用户的需求。
// 默认配置
splitChunks: {
chunks: "async",
minSize: 30000,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
name: true,
cacheGroups: {
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
}
}
}
weback3的配置
new webpack.optimize.CommonsChunkPlugin({
name: "common",
minChunks: 2,
minSize: 30000
})
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: module => {
return module.resource && /node_modules/.test(module.resource)
}
}),
// webpack 自身的这部分代码分离出来
new webpack.optimize.CommonsChunkPlugin({
name: "runtime",
minChunks: Infinity
})
为了避免由于文件名字没有改变,浏览器误以为我们文件的内容没有改变,直接使用内存中的缓存,而造成不必要的后果,配置chunkhash
output: {
filename: '[name].[chunkhash].bundle.js',
path: path.resolve(__dirname, 'dist')
}
使得每次修改都会产生一个唯一的hash后缀,以区别文件名,使得浏览器可以使用到最新版本的代码。 wbepack4之前,会因为webpack自身的样板和mainifest,会造成即使没有修改代码,但是再次打包出来的代码名称中的hash却改变的问题,需要通过插件来提取出来。
// webpack4中取消了该插件
new webpack.optimize.CommonsChunkPlugin({
name: "runtime",
minChunks: Infinity
})
// webpack4
optimization.runtimeChunk: true
用到vue-loader
和vue-style-loader
module: {
// .vue文件中使用css需要css-loader
// vue-style-loader是vue-loader的dependencies
// css-loader 是 vue-loader的peerDependencies
rules: [
{
test: /\.js$/,
use: 'babel-loader',
include: [path.resolve(__dirname, '../src')]
},
{
test: /\.vue$/,
use: ['vue-loader']
},
{
test: /\.css$/,
use: ['vue-style-loader', 'css-loader']
},
{
test: /\.s[ac]ss$/,
use: ['vue-style-loader', 'css-loader', 'sass-loader']
}
]
}
gulp的配置文件为 gulpfile.js 其中有几个关键和 api
的概念:
gulp的配置可以说是由一个个的任务组成,每个任务都由一个名字(自定义或者default),可以通过命令指定要执行的任务。
// 执行default任务
gulp
// 执行特点任务
gulp name
任务的完成通常需要插件的帮助,常用插件有:
gulp.task('script', function () {
gulp.src('./src/**/*.js')
.pipe(uglify())
.pipe(gulp.dest('dist'))
});
gulp.task('default', ['script'], function () { gulp.watch('./src/js/*.js', ['script']); });
### 执行顺序
gulp中的任务,在默认情况下,会·已最大的并发数同时运行,也就是说,它会不做任何等待地将所有的任务同时开起来。如果你希望创建一个有特定顺序的**串行**的任务链,你需要做两件事:
1. 给它一个提示,用以告知任务在什么时候完成,
2. 而后,再给一个提示,用以告知某任务需要依赖另一个任务的完成。
官方两个例子:
```js
var gulp = require('gulp');
// 传入一个回调函数,因此引擎可以知道何时它会被完成
gulp.task('one', function(cb) {
// 做一些事 -- 异步的或者其他任何的事
cb(err); // 如果 err 不是 null 和 undefined,流程会被结束掉,'two' 不会被执行
});
// 标注一个依赖,依赖的任务必须在这个任务开始之前被完成
gulp.task('two', ['one'], function() {
// 现在任务 'one' 已经完成了
});
gulp.task('default', ['one', 'two']);
// 也可以这么写:gulp.task('default', ['two']);
var gulp = require('gulp');
var del = require('del'); // rm -rf
gulp.task('clean', function(cb) {
del(['output'], cb);
});
gulp.task('templates', ['clean'], function() {
var stream = gulp.src(['src/templates/*.hbs'])
// 执行拼接,压缩,等。
.pipe(gulp.dest('output/templates/'));
return stream; // 返回一个 stream 来表示它已经被完成
});
gulp.task('styles', ['clean'], function() {
var stream = gulp.src(['src/styles/app.less'])
// 执行一些代码检查,压缩,等
.pipe(gulp.dest('output/css/app.css'));
return stream;
});
gulp.task('build', ['templates', 'styles']);
// templates 和 styles 将会并行处理
// clean 将会保证在任一个任务开始之前完成
// clean 并不会被执行两次,尽管它被作为依赖调用了两次
gulp.task('default', ['build']);
gulp
是什么
gulp是一个自动化构建工具,用来优化前端工作流程,可以帮助我们进行代码编译,压缩,图片压缩,资源合并等工作。
webpack
是什么
webpack是一个模块化资源打包工具,它支持多种模块化的方案,当 webpack 处理应用程序时,它会递归地构建一个依赖关系图(dependency graph),其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。并且通过对应的 loader ,我们还可以处理其他类型的文件,比如css,image。通过plugins还可以对代码进行压缩等操作。