原文转载于 www.rails365.netjavascript
原文: A tale of Webpack 4 and how to finally configure it in the right waycss
开始新的项目html
mkdir webpack-4-tutorial
cd webpack-4-tutorial
npm init
复制代码
上下会初始化一个项目,接下来添加webpack4.java
npm install webpack webpack-cli --save-dev
复制代码
肯定装的webpack版本是4.node
接下来修改package.jsonwebpack
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack"
},
复制代码
保存以后,npm run dev
会出现一个错误.git
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
下没有找到入口模块。es6
咱们来改下,再次打开package.json
github
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack --mode development"
},
复制代码
在项目下新建src
文件夹,而后src
下新建index.js
.web
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"
},
复制代码
而后再运行编译,也是能够正常编译。
在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!');
复制代码
如何解决?
两种办法:
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名称都将改变。
方法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你们应该不会陌生了。
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()
]
};
复制代码
这里使用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
文件夹