世界上最伟大的投资就是投资自己的教育
webpack4 正确的配置方式
原文: A tale of Webpack 4 and how to finally configure it in the right way
基本构建
开始新的项目
mkdir webpack-4-tutorial
cd webpack-4-tutorial
npm init
上下会初始化一个项目,接下来添加 webpack4.
npm install webpack webpack-cli --save-dev
确定装的 webpack 版本是 4.
接下来修改 package.json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack"
},
保存之后,npm run dev
会出现一个错误.
Insufficient number of arguments or no entry found.
Alternatively, run 'webpack(-cli) --help' for usage info.
Hash: 4442e3d9b2e071bd19f6
Version: webpack 4.12.0
Time: 62ms
Built at: 2018-06-22 14:44:34
WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/concepts/mode/
ERROR in Entry module not found: Error: Can't resolve './src' in '~/workspace/webpack-4-tutorial'
两个问题,第一个出错的意思是说,没有设置mode
,默认会认为是production
模式。第二个是说src
下没有找到入口模块。
我们来改下,再次打开package.json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack --mode development"
},
在项目下新建src
文件夹,然后src
下新建index.js
.
console.log(“hello, world”);
保存后再次运行npm run dev
.
这时候成功打包,发现项目里多了一个dist
文件夹. 这是因为 webpack4 是号称 0 配置,所以很多东西都给你配置好了,比如默认的入口文件,默认的输出文件。
在 webpack 中配置环境,基本都是两个配置文件 (development
, production
).在webpack4
中,有这两个模式来区分。
"scripts": {
"dev": "webpack --mode development",
"build": "webpack --mode production"
}
保存后运行npm run build
,你会发现main.js
文件小了很多。
上面很多东西都是通过默认配置来的,尝试去重写配置,在不使用配置文件的情况下。
"scripts": {
"dev": "webpack --mode development ./src/index.js --output ./dist/main.js",
"build": "webpack --mode production ./src/index.js --output ./dist/main.js"
},
编译转换你的代码
es6
就是未来,可是现在的浏览器对他的支持不是很好,我们需要babel
来转换他。
npm install babel-core babel-loader babel-preset-env --save-dev
bable 的配置,需要创建一个文件去配置。
新建.babelrc
文件,写入如下内容
{
"presets": [
"env"
]
}
接下来需要配置babel-loader
,可以在package.json
文件配置,但是还是独立出去好,比较好维护。项目下新建一个webpack.config.js
.加入一些基础配置。
// webpack v4
const path = require('path');
module.exports = {
entry: { main: './src/index.js' },
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'main.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}
]
}
};
然后package.json
的脚本可以去除一些配置.
"scripts": {
"dev": "webpack --mode development",
"build": "webpack --mode production"
},
然后再运行编译,也是可以正常编译。
Html && Css
在dist
文件夹下新建一个index.html
的文件.
<html>
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div>Hello, world!</div>
<script src="main.js"></script>
</body>
</html>
上面这段代码,使用到了style.css
. 接来下去处理css
的问题.
src
文件夹下新建style.css
。
div {
color: red;
}
然后在 js 文件中引入 css.,打开index.js
文件
import "./style.css";
console.log("hello, world");
解析来我们就需要配置css
的规则,打开webpack.config.js
// webpack v4
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin'); //新加入
module.exports = {
entry: { main: './src/index.js' },
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'main.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract(
{
fallback: 'style-loader',
use: ['css-loader']
})
}// 新加的css 规则
]
}
};
上面我们用了一些插件和加载器.需要去安装.
npm install extract-text-webpack-plugin --save-dev
npm install style-loader css-loader --save-dev
上面我们提出 css 来编译,你可以看到他的规则, 规则可以这样认为
{
test: /\.拓展名$/,
exclude: /不需要执行的文件夹/,
use: {
loader: "你的加载器"
}
}
我们需要extract-text-webpack-plugin
这个提取插件,因为webpack
只会辨别js
.这里需要通过ExtractTextPlugin
获取 css 文本进行压缩。
我们再次尝试编译,npm run dev
发现会有报错,这个是因为这个提取器在新版本的原因。相关报错 Webpack 4 compatibility
可以解决这个问题,那就是换个版本。
npm install -D extract-text-webpack-plugin@next
然后再编译,发现可以来,同时再dist
下有一个 style.css 文件。
这时候package.json
的依赖文件如下
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.4",
"babel-preset-env": "^1.6.1",
"css-loader": "^0.28.11",
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"style-loader": "^0.20.3",
"webpack": "^4.4.1",
"webpack-cli": "^2.0.12"
}
下面我们来配置支持scss
npm install node-sass sass-loader --save-dev
我们在src
下新建一个index.html
<html>
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div>Hello, world!</div>
<script src="main.js"></script>
</body>
</html>
安装html
插件
npm install html-webpack-plugin --save-dev
安装完成之后来修改webpack.config.js
// webpack v4
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');// 新加
module.exports = {
entry: { main: './src/index.js' },
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'main.js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract(
{
fallback: 'style-loader',
use: ['css-loader']
})
}// 新加
]
},
plugins: [
new ExtractTextPlugin({filename: 'style.css'}),
new HtmlWebpackPlugin({
inject: false,
hash: true,
template: './src/index.html',
filename: 'index.html'
})// 新加
]
};
这个是最终的 html 的一个模版. 现在html
,css
,js
基本配置的差不多,我们删除dist
来试试。
rm -rf dist/
npm run dev
这时候会发现dist
下存在js,css,html
文件.
缓存
可以查看关于hash 缓存的文档来使浏览器只请求改变的文件.
webpack4 提供了chunkhash来处理。
来看看:
// webpack v4
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');// 新加
module.exports = {
entry: { main: './src/index.js' },
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[chunkhash].js' //changed
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract(
{
fallback: 'style-loader',
use: ['css-loader']
})
}// 新加
]
},
plugins: [
new ExtractTextPlugin(
{filename: 'style.[chunkhash].css', disable: false, allChunks: true}
), //changed
new HtmlWebpackPlugin({
inject: false,
hash: true,
template: './src/index.html',
filename: 'index.html'
})
]
};
然后src
下的html
也要修改
<html>
<head>
<link rel="stylesheet" href="<%=htmlWebpackPlugin.files.chunks.main.css %>">
</head>
<body>
<div>Hello, world!</div>
<script src="<%= htmlWebpackPlugin.files.chunks.main.entry %>"></script>
</body>
</html>
可以发现这里改变来,这个是使模版使用 hash.
好了,现在可以编译,会发现dist
下的 css 和 js 名字是带有 hash 指的。
缓存带来的问题,如何解决
如果我们改变代码,在编译的时候,发现并没有生成创新的 hash 名文件。
div {
color: 'red';
background-color: 'blue';
}
再次进行编译npm run dev
,发现并没有生产新的 hash 文件名称,但是如果改变 js 代码,再次编译,会发现是改变了 hash 名称
import "./index.css"
console.log('Hello, world!');
如何解决?
两种办法:
- 方法 1 把 css 提取器中的 [chunkhash] 换成 [hash].但是这个会与 webpack4.3 中的contenthash有冲突.可以结合webpack-md5-hash一起使用。
npm install webpack-md5-hash --save-dev
// webpack v4
const path = require('path');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WebpackMd5Hash = require('webpack-md5-hash'); //新加
module.exports = {
entry: { main: './src/index.js' },
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[chunkhash].js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.css$/,
use: ExtractTextPlugin.extract(
{
fallback: 'style-loader',
use: ['css-loader']
})
}
]
},
plugins: [
new ExtractTextPlugin(
{filename: 'style.[hash].css', disable: false, allChunks: true}
),//changed
new HtmlWebpackPlugin({
inject: false,
hash: true,
template: './src/index.html',
filename: 'index.html'
}),
new WebpackMd5Hash() //新加
]
};
然后编译查看是否改变。
现在的变化是,改变 css 文件,那么 css 文件的 hash 名字改变。如果改变 js 文件,那么 css 和 js 的压缩 hash 名称都将改变。
- 方法 2(推荐)
方法 1 可能还会存在其他的冲突,所以来尝试下mini-css-extract-plugin
这个插件是为了取代 extract-plugin, 并带来兼容性的改变
npm install --save-dev mini-css-extract-plugin
尝试使用
// webpack v4
const path = require('path');
// const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WebpackMd5Hash = require('webpack-md5-hash');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");//新加
module.exports = {
entry: { main: './src/index.js' },
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[chunkhash].js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
// {
// test: /\.css$/,
// use: ExtractTextPlugin.extract(
// {
// fallback: 'style-loader',
// use: ['css-loader']
// })
// }
{
test: /\.(scss|css)$/,
use: [ 'style-loader', MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader']
} // 新加
]
},
plugins: [
// new ExtractTextPlugin(
// {filename: 'style.[hash].css', disable: false, allChunks: true}
// ),
new MiniCssExtractPlugin({
filename: 'style.[contenthash].css',
}),//新加
new HtmlWebpackPlugin({
inject: false,
hash: true,
template: './src/index.html',
filename: 'index.html'
}),
new WebpackMd5Hash()
]
};
好了,接下来我们尝试改变文件会怎么变化。
改变 css,进行编译发现只有 css 的文件改变来。改变 js 文件,发现编译之后只有 js 的 hash 名称改变,不错,就是这样。
继承 PostCss
postcss大家应该不会陌生了。
npm install postcss-loader --save-dev
npm i -D autoprefixer
-D.
创建postcss.config.js
module.exports = {
plugins: [
require('autoprefixer')
]
}
然后来配置你的webpack.config.js
// webpack v4
const path = require('path');
// const ExtractTextPlugin = require('extract-text-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WebpackMd5Hash = require('webpack-md5-hash');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: { main: './src/index.js' },
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[chunkhash].js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.(scss|css)$/,
use: [ 'style-loader', MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader']//changed
}
]
},
plugins: [
// new ExtractTextPlugin(
// {filename: 'style.[hash].css', disable: false, allChunks: true}
// ),
new MiniCssExtractPlugin({
filename: 'style.[contenthash].css',
}),
new HtmlWebpackPlugin({
inject: false,
hash: true,
template: './src/index.html',
filename: 'index.html'
}),
new WebpackMd5Hash()
]
};
保持 dist 整洁
这里使用clean-webpack-plugin
插件.
npm i clean-webpack-plugin --save-dev
// webpack v4
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WebpackMd5Hash = require('webpack-md5-hash');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CleanWebpackPlugin = require('clean-webpack-plugin');//新加
module.exports = {
entry: { main: './src/index.js' },
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[chunkhash].js'
},
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.(scss|css)$/,
use: [ 'style-loader', MiniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader']//changed
}
]
},
plugins: [
// new ExtractTextPlugin(
// {filename: 'style.[hash].css', disable: false, allChunks: true}
// ),
new CleanWebpackPlugin('dist', {} ),//新加
new MiniCssExtractPlugin({
filename: 'style.[contenthash].css',
}),
new HtmlWebpackPlugin({
inject: false,
hash: true,
template: './src/index.html',
filename: 'index.html'
}),
new WebpackMd5Hash()
]
};
这样每次编译的时候,就会清空dist
文件夹
本站文章均为原创内容,如需转载请注明出处,谢谢。
© 汕尾市求知科技有限公司 | Rails365 Gitlab | 知乎 | b 站 | csdn
粤公网安备 44152102000088号 | 粤ICP备19038915号
Top
写的非常棒 谢谢🌹
谬赞了,有帮助就好,加油
写里个 webpack4 配置 react 的版本,打算在项目里试试水