原文链接:Webpack 4 Tutorial: from 0 Conf to Production Mode
webpack 4 问世了!除了大幅度的性能提升,而且增加了零配置的默认设置。
webpack 是一个强力和有着很多独特功能的工具,但是他的一大痛点在于他的配置文件
如果是大中型项目我添加配置文件没什么大问题,有时候也是必须的。但是有时候就随便弄个项目来玩玩,还要添加配置文件,嗯,很不友好。
这也是 Parcel 之所以受欢迎的原因
现在的好消息是 webpack 4 默认也不需要配置文件了!撒花撒花~ ?
创建一个目录然后进入
mkdir webpack-4-quickstart && cd $_初始化 package.json:
npm init -y安装 webpack4:
npm i webpack --save-dev还需要安装另外一个包:webpack-cli
npm i webpack-cli --save-dev然后打开 package.json 添加构建脚本:
"scripts": { "build": "webpack" }试着运行
npm run build然后我们看到
ERROR in Entry module not found: Error: Can't resolve './src' in '~/webpack-4-quickstart'OJBK! 没有找到入口文件。
简要来说:webpack 需要这个入口文件来开始 js 代码的打包。
在以前的版本里 webpack 的入口文件需要在配置文件 webpack.config.js 里指定。
但是现在不需要了,它会默认选择 ./src/index.js 这个文件。
测试这个新特性很容易,创建一个 ./src/index.js:
console.log(`I'm a silly entry point`)重新试试构建:
npm run build你会在 ~/webpack-4-quickstart/dist/main.js 得到你打包后的文件。
咦?等一下。都不需要指定输出文件吗?是的。
在 webpack 4 中是不需要指定入口和输出文件。
webpack 的真正本领是代码拆分。但是相信我,有一个零配置的工具可以让你更加高效。
所以这就是第一个新特性:他会把 ./src/index.js 默认为入口文件,把打包后的文件放在 ./dist/main.js。
下一章后我们能看到另一个有用的特性:生产和开发模式。
在项目中整两份配置文件是很正常的事了。
一个典型的例子:
一个开发用的配置文件,用来定义 webpack 的 dev server 和其他东西一个生产环境用的配置文件,用来定义 UglifyJSPlugin,sourcemap 和其他东西。但是在 webpack4 中你能够不写一行配置。
咋这么流弊呢?
webpack 4 介绍了生产( production) 和开发( development) 两种模式。
实际上如果你关注过 npm run build 的输出信息你会看到这个警告:
The ‘mode’ option has not been set. Set ‘mode’ option to ‘development’ or ‘production’ to enable defaults for this environment.
这是什么意思?我们看看。
打开 package.json 文件添加如下脚本
"scripts": { "dev": "webpack --mode development", "build": "webpack --mode production" }现在运行:
npm run dev查看 ./dist/main.js 文件。你看到了什么?嘿嘿,嗯,他没有被压缩!
现在这样:
npm run build现在再看,你看到什么?是不是压缩了!
是的!
生产模式开启了一系列额外的优化。包括 minification, scope hoisting, tree-shaking 等, 点赞 ?。
另外开发模式为了优化速度,就没有做压缩了。
所以这是第二个新特性:生产和开发模式。
在 webpack4 你不需要一行配置,只需要一个 --mode 选项。
我喜欢 webpack4 的零配置,但是,如果我要覆盖默认的入口或者出口配置要怎么做呢?
在 package.json 里配置他们。
比如:
"scripts": { "dev": "webpack --mode development ./foo/src/js/index.js --output ./foo/main.js", "build": "webpack --mode production ./foo/src/js/index.js --output ./foo/main.js" }现在大家都习惯用 ES6 写 Javascript。
但是不是所有浏览器都知道怎么处理 ES6。我们需要做一些转换。
这个转换的步骤叫做 transpiling。transpiling 是指把 ES6 转译成浏览器能够识别的代码。
webpack 本身并不知道如何去转换,但是有 loaders。把他们想象成转换器。
babel-loader 是 webpack 的一个 loader,可以把 ES6 以上的代码转译成 ES5。
为了使用这个 loader 我们需要去安装一系列的依赖。特别是:
babel-corebabel-loaderbabel-preset-env (for compiling Javascript ES6 code down to ES5)先安了吧:
npm i babel-core babel-loader babel-preset-env --save-dev下一步我们在项目目录下建立一个 .babelrc 文件用来配置 Babel。
{ "presets": ["env"] }在这里我们有两个途径去配置 babel-loader:
用 webpack 的配置文件在 npm 脚本里使用 --module-bind擦,说好的零配置呢,这怎么又跟我谈配置,童话里都是骗人的。
So,为什么我们又要写配置文件了呢。
原来 webpack 4 的零配置指的是:
入口文件。默认是 ./src/index.js出口文件。默认是 ./dist/main.js生产和开发模式(无需创建两套配置文件)就这些了。对于 loaders 我们仍然需要使用配置文件哦,微笑 ?。
作者就这件事问过 Sean(webpack 的核心开发者)。在 webpack 4 中 loaders 是否和 webpack 3 中没有区别?有计划对这些通用的 loaders 比如 babel-loader 提供零配置吗?
他的回答是:
在未来的版本(v4 之后,可能是 4.x 或者 5.0),我们已经开始探索预设或附加系统如何帮助我们定义这一点。我们不想要的是:把一堆东西塞到核心代码里去。我们需要的是:能够支持扩展。
对于现在来说你仍必须依赖 webpack.config.js。
创建一个名叫 webpack.config.js 的文件然后配置 loader:
module.exports = { module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader' } } ] } }没有必要去指定入口文件除非你想指定。
下一步打开 ./src/index.js 然后写一些 ES6 代码:
const arr = [1, 2, 3] const iAmJavascriptES6 = () => console.log(...arr) window.iAmJavascriptES6 = iAmJavascriptES6最后打包:
npm run build然后去 ./dist/main.js 看看转换后的代码。
还有一种使用 webpack loaders 的方法。
--module-bind 选项让你从命令行指定 loaders。
这个选项并不是 webpack 4 独有的。3 开始就有了。
你可以这样在 package.json 中使用:
"scripts": { "dev": "webpack --mode development --module-bind js=babel-loader", "build": "webpack --mode production --module-bind js=babel-loader" }然后你就可以开始构建了。
我并不是很喜欢这种方法(不喜欢太长的 npm 脚本),尽管如此它很有趣。
如果你已经安装配置好了 babel 这会很简单。
安装 React:
npm i react react-dom --save-dev添加 babel-preset-react:
npm i babel-preset-react --save-dev在 .babelrc 里配置 preset
{ "presets": ["env", "react"] }这样就可以了。
如 Conner Aiken 建议的你可以配置 babel-loader 也去加载 .jsx 文件。这在你使用 jsx 扩展名的时候很有用。
打开 webpack.config.js 然后这样配置:
module.exports = { module: { rules: [ { test: /\.(js|jsx)$/, exclude: /node_modules/, use: { loader: 'babel-loader' } } ] } }测试是否搭好你可以在 ./src/App.js 里创建一个 React 组件。
import React from 'react' import ReactDOM from 'react-dom' const App = () => { return ( <div> <p>React here!</p> </div> ) } export default App ReactDOM.render(<App />, document.getElementById('app'))然后在 ./src/index.js 中引入:
import App from './App'重新构建试试
webpack 需要两个额外的组件去处理 HTML:html-webpack-plugin 和 html-loader。
添加这两个依赖:
npm i html-webpack-plugin html-loader --save-dev然后更新 webpack 的配置
const HtmlWebPackPlugin = require('html-webpack-plugin') module.exports = { module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader' } }, { test: /\.html$/, use: [ { loader: 'html-loader', options: { minimize: true } } ] } ] }, plugins: [ new HtmlWebPackPlugin({ template: './src/index.html', filename: './index.html' }) ] }在 ./src/index.html 新建一个 HTML 文件:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>webpack 4 quickstart</title> </head> <body> <div id="app"> </div> </body> </html>运行:
npm run build查看 ./dist 目录。你会看到运行后的结果。
没有必要在你的 HTML 文件中引入你的 JavaScript:它会自动地注入进去。
在浏览器打开 ./dist/index.html:你可以看到 React 组件运行起来了!
如你所见在处理 HTML 上并没有什么新变化。
webpack 4 目前仍然是一个针对 js 的模块的打包工具。
但是有这个想法,就是添加 HTML 作为一个模块(比如把 HTML 作为入口文件)。
webpack 并不知道怎么去提取 CSS 到文件中。
在之前这都是交给 extract-text-webpack-plugin 完成的。
不幸的是这个插件在 webpack 4 已经实在玩不动了。
Michael Ciniawsky 说:
维护 extract-text-webpack-plugin 是一个很大的负担,而且这不是第一次因为这货不给力,使得升级 webpack 的主版本都变得异常艰难。
这货被拍死在沙滩后,mini-css-extract-plugin 是来替代它的。
提示:你得把 webpack 版本升级到 4.2.0,才能用这个插件!
安装它:
npm i mini-css-extract-plugin css-loader --save-dev然后建立一个 CSS 文件用来测试:
/* */ /* CREATE THIS FILE IN ./src/main.css */ /* */ body { line-height: 2; }配置 loader 和 plugin:
const HtmlWebPackPlugin = require('html-webpack-plugin') const MiniCssExtractPlugin = require('mini-css-extract-plugin') module.exports = { module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: { loader: 'babel-loader' } }, { test: /\.html$/, use: [ { loader: 'html-loader', options: { minimize: true } } ] }, { test: /\.css$/, use: [MiniCssExtractPlugin.loader, 'css-loader'] } ] }, plugins: [ new HtmlWebPackPlugin({ template: './src/index.html', filename: './index.html' }), new MiniCssExtractPlugin({ filename: '[name].css', chunkFilename: '[id].css' }) ] }最后在入口文件中引入 CSS:
// PATH OF THIS FILE: ./src/index.js import style from './main.css'构建:
npm run build查看 ./dist 目录,你应该能看到 CSS 的结果!
重点回顾:extract-text-webpack-plugin 在 webpack 4 中不能用了。请使用 mini-css-extract-plugin。
在你改变代码后运行 npm run dev?这不是个理想的做法。花几分钟去配置下 webpack 的开发服务。一旦配置了 webpack dev server 它会在浏览器中加载你的 app。
只要你改变了文件,它会自动地刷新浏览器的页面。
安装下面的包来搭建 webpack dev server:
npm i webpack-dev-server --save-dev然后打开 package.json 调整脚本:
"scripts": { "start": "webpack-dev-server --mode development --open", "build": "webpack --mode production" }保存关闭。
现在运行:
npm run start你就会看到 webpack dev server 在浏览器中加载你的应用了。
webpack dev server 非常适合用来开发。(而且它能使得的 React Dev Tools 在浏览器中正常的工作)