好几天没写博客了,今天在想博客怎么处理,突然发现大神 博客 有很多前端视频教程,就顺便把之前学的 Webpack 补一补,之前的 《纯 React&纯 Redux》 的笔记中的 Webpack 和这个 Webpack 2 互为补充,我就不做分离了。因为是给自己看的,所以这是个超级不负责任的笔记。
Webpack 前端资源模块化管理和打包工具。通过加载器 (loader) 的转换,任何形式的资源都可以视为模块。
在 《React 与 Redux 开发实例精解》 Webpack 做这些事。
- 编译、加载使用 ES2015 和 JSX 语法的模块
- 实现开发服务器和热替换
- 加载图片文件
- 加载字体文件
- 加载样式文件
- 加载 Json 文件
- 使用同构工具实现同构渲染
- 压缩代码
- 哈希命名
这个不说了,看视频
初始工作:
1 2 3 4
|
$ mkdir 003 $ npm init -y
|
安装 webpack 模块:
1 2
| $ npm install webpack --save-dev $ npm install webpack -g
|
创建文件:
1 2 3
| $ mkdir app $ cd app $ touch index.js
|
1 2
| console.log("hello world")
|
打包:
1
| $ webpack app/index.js build/bundle.js
|
经过这一步,build
文件夹下面就会出现一个bundle.js
文件
下面,我们来使用一个插件,来体验一下用 webpack 做网页。
准备:
1 2
| $ npm install html-webpack-plugin --save-dev $ touch webpack.config.js
|
编写代码:
1 2 3
| import component from './component.js' document.body.appendChild(component())
|
1 2 3 4 5 6
| export default (text = 'hello world') => { const element = document.createElement('div'); element.innerHTML = text; return element }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| const path = require('path') const HtmlWebpackPlugin = require('html-webpack-plugin')
const PATHS = { app: path.join(__dirname, 'app'), build: path.join(__dirname, 'build') };
module.exports = { entry: { app: PATHS.app, }, output: { path: PATHS.build, filename: '[name].js', }, plugins: [ new HtmlWebpackPlugin({ title: 'Webpack demo' }) ] }
|
运行:
结果:
1 2 3
| build ├── app.js └── index.html#这是我用插件帮忙生成的
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| ➜ 004 webpack Hash: cc2d357e75c09b6ce858 Version: webpack 3.0.0# 版本 Time: 884ms
Asset Size Chunks Chunk Names app.js 3.06 kB 0 [emitted] app index.html 180 bytes [emitted]
[0] ./app/index.js 78 bytes {0} [built] [1] ./app/component.js 135 bytes {0} [built]
Child html-webpack-plugin for "index.html": [2] (webpack)/buildin/global.js 509 bytes {0} [built] [3] (webpack)/buildin/module.js 517 bytes {0} [built] + 2 hidden modules
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| { "name": "004", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "webpack --env production" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "html-webpack-plugin": "^2.29.0", "webpack": "^3.0.0" } }
|
运行:
查看scripts
命令
如果想看 package.json
中的脚本有哪些,再也不用手动打开 package.json
文件了。
1 2 3 4 5 6 7 8
| $ npm run Lifecycle scripts included in 004:#项目名 004 test echo "Error: no test specified" && exit 1
available via `npm run-script`: build webpack --env production
|
安装 webpack-dev-server
1
| $ npm i webpack-dev-server --save-dev
|
配置 script:
1 2 3 4
| "script":{ ... "start":"webpack-dev-server --env development" }
|
运行:
1 2 3 4 5 6 7 8
| module.exports ={ devServer: { host: process.env.HOST, port: process.env.PORT }, ... }
|
配置一个 ESLint 来虐自己吧 O(∩_∩)O
安装:
配置:
1 2 3 4 5
| "script":{ .... "lintjs": "eslint app/ webpack.*.js --cache" }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| module.exports = { env: { browser: true, commonjs: true, es6: true, node: true, }, extends: 'eslint:recommended', parserOptions: { sourceType: 'module', }, rules: { 'comma-dangle': ['error', 'always-multiline'], indent: ['error', 2], 'linebreak-style': ['error', 'unix'], quotes: ['error', 'single'], semi: ['error', 'always'], 'no-unused-vars': ['warn'], 'no-console': 0, }, };
|
运行:
自动修复 error:
1
| $ npm run eslintjs --fix
|
上一节好麻烦,现在我们来一边打包一边检测
安装加载器:
1
| npm i eslint-loader --save-dev
|
配置加载器:
1 2 3 4 5 6 7 8 9 10 11 12
| module: { rules: [{ test: /\.js$/, enforce: 'pre',
loader: 'eslint-loader', options: { emitWarning: true, }, }] }
|
运行:
浏览器显示 ESLint 错误:
为了不用切换 Terminal 、Chrome、sublime 之前切换,我们把错误直接抛到显示器上,Terminal 只处理打包,Chrome 看语法错误,在 sublime 修改就好了。
1 2 3 4 5 6 7 8 9 10 11 12
| module.exports = { devServer: { host: process.env.HOST, port: 80, overlay: { errors: true, warnings: true, }, }, ... }
|
webpack 除了能打包 js 文件,我们还能打包各种资源,这次先来栏加载 css 文件的加载方法。
安装加载器:
1
| $ npm i css-loader style-loader --save-dev
|
配置:
1 2 3 4 5 6 7 8 9 10 11 12 13
| test: /\.css$/, exclude: /node_modules/, use: [ 'style-loader', { loader: 'css-loader', options: { modules: true, }, }, ] }
|
为了防止 CSS 同名冲突。所以就有了这个。用上一节的配置,写上注释
1 2 3 4 5 6 7 8 9 10 11 12 13
| test: /\.css$/, exclude: /node_modules/, use: [ 'style-loader', { loader: 'css-loader', options: { modules: true, }, }, ] }
|
之前所以的 css、js 都打包成了 js。而浏览器最后才加载 js。如果把 css 放在 js 中,网页刷新就会闪一下,因为网页在没有加载 js 时,是没有 css 样式的(有浏览器默认样式)。所以我们有必要把 css 分离出来。
安装:
1
| $ npm i extract-text-webpack-plugin --save-dev
|
配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| const ExtractTextPlugin = require('extract-text-webpack-plugin'); const plugin = new ExtractTextPlugin({ filename: '[name].css', ignoreOrder: true, });
reles:[{ test: /\.css$/, exclude: /node_modules/, use: plugin.extract({ use: { loader: 'css-loader', options: { modules: true, }, }, fallback : 'style-loader', }), }]
plugins: [ new HtmlWebpackPlugin({ title: 'Webpack demo', }), plugin, ]
|
一般 loader 加载顺序是从右到左的,当然你可以设置前置加载,把东西提到前面先加载。
这节太难了吧,自己去文档看。
自动检查大小:
1 2 3 4 5 6
| performance: { hints: 'warning', maxEntrypointSize: 100000, maxAssetSize: 450000, },
|
webpack 命令压缩:
插件压缩:
1
| npm i babili-webpack-plugin --save-dev
|
1 2 3 4 5 6 7 8 9 10 11
| const BabiliPlugin = require('babili-webpack-plugin');
plugins: [ new HtmlWebpackPlugin({ title: 'Webpack demo', }), plugin, new BabiliPlugin(), ]
|
为什么要用这个?:
webpack 对我们的代码进行了混淆,调试根本没法用了。所以我们需要这个东西,视频的例子貌似还有自己找文件,我自己在 《纯 React&纯 Redux》 中记录了另一个方法。
1 2 3 4
|
devtool: 'source-map',
|
1 2 3 4 5 6
| entry:{ app: PATHS.app, vendor:['react'] }
|
1 2 3 4 5 6 7 8 9 10
| plugins: [ new HtmlWebpackPlugin({ title: 'Webpack demo', }), plugin, new BabiliPlugin(), new webpack.optimize.CommonsChunkPlugin({ name: 'vendor', }), ],
|
引入的时候先 vendor 在 app
1 2 3
| "script":{ "stats": "webpack --env production --profile --json > stats.json" }
|
官方可视化工具
webpack-chart
使用可视化图表对 Webpack 2 的编译与打包进行统计分析
看视频
看视频,不写了
—————- 分割线 —————-
参考资料
Webpack 中文文档:
Webpack 教程:
其他: