成为一个全栈工程师,前端是必不可少的,这位前端构建工具webpack是一门必修的技术。javascript
在学习webpack以前,先熟悉一下npm工具:https://www.runoob.com/nodejs/nodejs-npm.htmlcss
什么是webpack?html
webpack能够打包全部的样式,脚本,表,资源,生成一个或多个bundle,webpack 可以处理 JS 文件的互相依赖关系,可以处理JS的兼容问题,把高级的、浏览器不是别的语法,转为低级的浏览器能正常识别的语法。前端
官方文档:https://www.webpackjs.com/concepts/java
example参考:https://github.com/lemonzoey/webpack-demo node
1 初始化项目 npm init , 建立src,dist目录,在src下创建main.js,index.htmljquery
2 安装依赖包jquery : npm install jquerywebpack
3 安装webpack : npm install --save-dev webpackgit
mkdir webpack-study && cd webpack-study
npm init -y
npm install webpack webpack-cli --save-dev
4 编写项目github
main.js是项目的JS入口文件
// 这是 main.js 是咱们项目的JS入口文件 // 1. 导入 Jquery // import *** from *** 是ES6中导入模块的方式 // 因为 ES6的代码,过高级了,浏览器解析不了,因此,这一行执行会报错 import $ from jquery // const $ = require('jquery') $(function () { $('li:odd').css('backgroundColor', 'yellow') $('li:even').css('backgroundColor', function () { return '#' + 'D97634' }) })
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <!-- 由于 main 中的代码,涉及到了ES6的新语法,可是浏览器不识别 --> <!-- <script src="./main.js"></script> --> <!-- 经过 webpack 这么一个前端构建工具, 把 main.js 作了一下处理,生成了一个 bundle.js 的文件 --> <script src="../dist/bundle.js"></script> </head> <body> <ul> <li>这是第1个li</li> <li>这是第2个li</li> <li>这是第3个li</li> <li>这是第4个li</li> <li>这是第5个li</li> <li>这是第6个li</li> <li>这是第7个li</li> <li>这是第8个li</li> <li>这是第9个li</li> <li>这是第10个li</li> </ul> </body> </html>
5 webpack编译打包main.js
webpack src/main.js --output dist/bundle.js
或者能够在根目录下建立 webpack.config.js
const path = require('path'); module.exports = { entry: './src/main.js', //入口 表示要打包的文件 output: { path: path.join(__dirname, './dist'),// 指定输出路径 filename: 'my-first-webpack.bundle.js' } };
再执行: webpack
固然执行命令能够交给npm管理,须要在package.json上添加
再执行命令 npm run build
加载css样式
1 安装资源加载器
npm install --save-dev style-loader css-loader
2 添加样式文件
3 添加webpack配置文件css资源加载
const path = require('path'); module.exports = { entry: './src/main.js', //入口 表示要打包的文件 output: { path: path.join(__dirname, './dist'),// 指定输出路径 filename: 'bundle.js' }, module:{ rules:[ { test:/\.css$/, use:[ 'style-loader', 'css-loader' ] } ] } };
4 修改main.js 添加css文件,使得资源文件被加载到bundle.js中
其余加载图片,字体,数据等资源,相同的操做步骤,可参考官方文档.
若是index.html中引用了多个bundle文件,若是这些bundle文件名称发生改变,而index.html还引用原来的bundle文件名,则会出错。
这个plugin就是让指定的html每次build的时候生成一个新的html文件,该文件引用最新的bundle文件。
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); module.exports = { entry: { // 存在多个入口文件 main: './src/main.js', print: './src/print.js' }, //入口 表示要打包的文件 output: { // 也输出多个bundle.js文件 path: path.join(__dirname, './dist'),// 指定输出路径 filename: '[name].bundle.js' }, plugins: [ new HtmlWebpackPlugin({ title: 'new Document' // title=new Document的html文件,会从新加载生成一个新的html }) ], module: { rules: [ { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] } ] } };
clean-webpack-plugin
清理/dist 文件夹
1 若是某个js发生错误,但愿可以定位到具体的js中,能够在webpack.config.js中添加以下选项
webpack-dev-server使用
npm install --save-dev webpack-dev-server
webpack.config.js
devServer: { contentBase: './dist' }
package.json
"start": "webpack-dev-server --open"
执行命令 npm run start
该功能容许运行时更新各个模块,而不是全量刷新.
webpack.config.js
const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const CleanWebpackPlugin = require('clean-webpack-plugin'); + const webpack = require('webpack'); module.exports = { entry: { - app: './src/index.js', - print: './src/print.js' + app: './src/index.js' }, devtool: 'inline-source-map', devServer: { contentBase: './dist', + hot: true }, plugins: [ new CleanWebpackPlugin(['dist']), new HtmlWebpackPlugin({ title: 'Hot Module Replacement' }), + new webpack.NamedModulesPlugin(), + new webpack.HotModuleReplacementPlugin() ], output: { filename: '[name].bundle.js', path: path.resolve(__dirname, 'dist') } };
package.json
"start": "webpack-dev-server --hotOnly"
若是全部代码都不包含反作用,那么能够删除一些未用到的export导出代码,
package.json
{ "name": "your-project", "sideEffects": false }
若是有反作用,能够指定文件{
"name": "your-project", "sideEffects": [ "./src/some-side-effectful-file.js", "*.css" ] }
1 建立多个环境配置文件
+|- webpack.common.js
+ |- webpack.dev.js
+ |- webpack.prod.js
2 安装
npm install --save-dev webpack-merge 用于合并多个配置文件 merge()
3 如开发配置
+ const merge = require('webpack-merge'); + const common = require('./webpack.common.js'); + + module.exports = merge(common, { + devtool: 'inline-source-map', + devServer: { + contentBase: './dist' + } + });
4 npm script

实际上编译出多个bundle代码,且公共部分提取到一个文件。避免重复模块引用到各个bundle中
动态导入
动态import模块,使得调用的时候编译出bundle文件。
实际上就是每一次文件bundle文件变动,可以变动文件名,使得客户端可以感知文件的变化。
只须要在webpack配置output的时候,文件名上添加hash段
output: {
- filename: 'bundle.js', + filename: '[name].[hash].js', path: path.resolve(__dirname, 'dist') }
提取模板manifest
...
new webpack.HashedModuleIdsPlugin() // 防止标识符moduleId的改变,致使无修改bundle刷新 // 用于生产环境 ], optimization: { splitChunks: { cacheGroups: { commons: { name: "vendor", // 生成共享模块bundle的名称 chunks: "initial",//”initial”, “async” 和 “all”. 分别对应优化时只选择初始的chunks,所须要的chunks 仍是全部chunks 。 minChunks: 2 //共享模块的chunks的最小数目 ,默认值是1 } } } }, optimization: { splitChunks: { cacheGroups: { commons: { name: "manifest", chunks: "initial", minChunks: 2 } } } },
webpack --env.NODE_ENV=local --env.production --progress
在项目中构建路径值,publicPath 也会在服务器脚本用到,以确保文件资源可以在 http://localhost:8080 下正确访问