2020/10/10 Webpack已经发布版本5了
如何开始学习:官网-指南-起步:https://v4.webpack.docschina.org/guides/getting-started/
初始化: 命令写在终端中
- 初始化package.json文件
npm init -y
// 结果: { "name": "demo1", "version": "1.0.0", "description": "", "main": "index.js", "scripts": {
"test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], "author": "", "license": "ISC"}
- 安装依赖
webpack要求node.js是10.0以上版本,否则会安装失败,可以去node.js官网下载升级
如下命令为本地安装,安装后生成node-modules目录,webpack和它的小伙伴cli在文件夹的.bin目录里。并非-g是全局安装
提醒:安装要很久很久的。。。可以刷刷淘宝
yarn add webpack webpack-cli --dev //会生成一个yarn.lock文件,准确存储每个安装的依赖是哪个版本,应该被提交到版本控制系统,发布它对库的用户不会有任何影响。
//或
npm install webpack webpack-cli --save-dev
// 结果我的版本:webpack 5.1.3 webpack-cli 4.0.0,可以在webpack和cli后用@指定版本号
- 编译js
创建src文件夹,,里面写index.js文件后。运行webpack打包
会生成main.js文件,里面就是index.js文件内容和兼容
./node_modules/.bin/webpack
// 或
npx webpack //会自己去找webpack的位置并运行,但不够稳定如果装node的位置有空格会找不到
// 结果:(()=>{"use strict";console.log("xxxx")})();
这一步操作之前可能因为没有设置开发还是生产模式产生warning,但现在没有
- 配置webpack.config.js
- 开发/生产模式
mode: "production" // "production" | "development" | "none"
- 入口和出口
entry: "./src/testentry.js",
output: {
// webpack 如何输出结果的相关选项
path: path.resolve(__dirname, "dist"), // string
// 所有输出文件的目标路径
// 必须是绝对路径(使用 Node.js 的 path 模块)
'[name].[hash].js' // [name]可以替换成自己想要的如index。加上hash这样会生成带20位数字的编译文件,方便浏览器识别有没有更新,要不要不理缓存,重新去下载
}
- 清理dist文件
安装清理插件clean-webpack-plugin
yarn add --dev clean-webpack-plugin
// 或
npm install --save-dev clean-webpack-plugin
再config.js增加命令
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
plugins: [
new CleanWebpackPlugin()
] // npm run build后会删除之前的dist中的旧文件
- 自动生成html文件
安装html-webpack-plugin插件
yarn add --dev html-webpack-plugin
// 或
npm install --save-dev html-webpack-plugin
再config.js增加命令
const HtmlWebpackPlugin = require('html-webpack-plugin');
plugins: [
new HtmlWebpackPlugin(),//生成默认index.html文件,即可以生成多个的
new HtmlWebpackPlugin({
title: '管理输出', // 如果自己下面的src里面的html有title,这里的设置会失效
filename: 'assets/admin.html', // 输出的dist里的路径和文件名
template: './src/index.html' // 模板html,就用这个啦
})
// 结果dist生成两个html,一个直接index.html,另一个在assets里的admin.html
如要使用配置里的title,可以在模板html里修改title如下:
<title><%= htmlWebpackPlugin.options.title %></title>
- 加载CSS
安装loader,创建css页面并import到js文件中
yarn add --dev style-loader css-loader // css loader把css内容读到js里面,style loader是把读到的内容放进html里面
// 或
npm install --save-dev style-loader css-loader
再config.js增加命令
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
],
},
],
},
// 结果:用http-server -c-1预览的html页面可以看到样式生效,且head里插入了style标签。注意dist的html没有style标签的
模块 loader 可以链式调用。链中的每个 loader 都将对资源进行转换。链会逆序执行。第一个 loader 将其结果(被转换后的资源)传递给下一个 loader,依此类推。最后,webpack 期望链中的最后的 loader 返回 JavaScript。
应保证 loader 的先后顺序:‘style-loader’ 在前,而 ‘css-loader’ 在后。如果不遵守此约定,webpack 可能会抛出错误。
- 生成css文件
安装插件mini-css-extract-plugin
npm install --save-dev mini-css-extract-plugin // 或yarn
建议 mini-css-extract-plugin 与 css-loader 一起使用。之后将 loader 与 plugin 添加到你的 webpack 配置文件中
再修改config.js文件
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
plugins: [
new MiniCssExtractPlugin({
filename: '[name].[hash].css',
})
],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
],
},
};
说明页面生成style标签与css文件二选一
- 使用watch mode(观察模式)
本地自动编译
指示 webpack “watch” 依赖图中所有文件的更改。如果其中一个文件被更新,代码将被重新编译,所以你不必再去手动运行整个构建
"scripts": {
"watch": "webpack --watch",
}
运行npm run watch,每次保存自动编译。
watch 触发增量构建后不删除 index.html 文件
new CleanWebpackPlugin({ cleanStaleWebpackAssets: false }),
// 结果不会删除之前dist里面的js文件了,很奇怪,还是不设置了吧
- 使用 webpack-dev-server
浏览器自动刷新
yarn add --dev webpack-dev-server
// 或
npm install --save-dev webpack-dev-server
再config.js增加命令
devServer: {
contentBase: './dist',
},
以上配置告知 webpack-dev-server,将 dist 目录下的文件 serve 到 localhost:8080 下
添加一个可以直接运行 dev server 的 script
"scripts": {
"start": "webpack serve", // "webpack-dev-server"官网写的是这个但实际运行会报错,可见issue:https://github.com/webpack/webpack-dev-server/issues/2759
}
运行npm start,浏览器会自动加载。现在更改任何源文件并保存它们,web server 将在编译代码后自动重新加载。
这个是不依赖于dist目录的,直接在内存就搞定了。
注意:“start”: “webpack serve”,官网写的 "webpack-dev-server"实际运行会报错,可见issue:https://github.com/webpack/webpack-dev-server/issues/2759
- 不同环境配置不同模式
如生产环境生成css文件,开发环境生成style标签
强行自己继承
开发和生产不同配置,将共同的配置放在config.js中,config.prod.js和config.dev.js分别去继承它
// package.json
"build": "webpack --config webpack.config.prod.js", // build的时候使用prod的配置
"start": "webpack serve --config webpack.config.dev.js ", // start的时候使用dev的配置
// config.js
const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
entry: "./src/index.js",
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: 'webpack很牛',
filename: 'index.html',
template: './src/index.html'
})
],
output: {
// webpack 如何输出结果的相关选项
path: path.resolve(__dirname, "dist"), // string
// 所有输出文件的目标路径
// 必须是绝对路径(使用 Node.js 的 path 模块)
filename: 'index.[hash].js'// string}
},
module: { },
}
// config.prod.js
const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const base = require('./webpack.config')
module.exports = {
...base,
mode: "production", // "production" | "development" | "none" // Chosen mode tells webpack to use its built-in optimizations accordingly.
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
],
},
],
},
}
// config.dev.js
const path = require('path');
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const base = require('./webpack.config')
module.exports = {
...base,
mode: "development",
devtool: 'inline-source-map',
devServer: {
contentBase: './dist',
}, // devtools和devServer是开发才用的
plugins: [
...base.plugins,
new MiniCssExtractPlugin({
filename: '[name].[hash].css',
})
],
module: {
rules: [
{
test: /\.css$/i,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
],
},
}
使用merge
安装yarn add --dev webpack-merge
再config.js引入
const { merge } = require('webpack-merge');
后续使用见:webpack-merge
- 引入scss
安装,注意node-sass已经过时了,安装dart-sass以替代
yarn add sass-loader dart-sass --dev
将 sass-loader 、css-loader 与 style-loader 进行链式调用,可以将样式以 style 标签的形式插入 DOM 中,或者使用 mini-css-extract-plugin 将样式输出到独立的文件中。
再写config.js
module: {
rules: [
{
test: /\.scss$/i,
use: [
// 将 JS 字符串生成为 style 节点
'style-loader',
// 将 CSS 转化成 CommonJS 模块
'css-loader',
// 将 Sass 编译成 CSS
{
loader: 'sass-loader',
options: {
implementation: require('dart-sass'),
}
}
//需要将sass携程上面的对象,否则会直接用node-sass加载,会报错
],
},
],
},
需注意同时安装 node-sass 和 sass 的情况!默认情况下,sass-loader 会选择 sass。 为了避免这种情况,你可以使用 implementation 选项。
implementation 选项可以以模块的形式接受 sass(Dart Sass)或 node-sass
- 引入less
安装less less-loader
yarn add less --dev
yarn add less-loader --dev
再改config.js
{
test: /\.less$/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
},
{
loader: 'less-loader',
options: {
lessOptions: {
strictMath: true,
},
},
},
],
},
// 下面这个简单的用法失败了
{
test: /\.less$/, // 失败的
loader: [ // 失败的
' style-loader', // 失败的
'css-loader', // 失败的
'less-loader' // 失败的
], // 将 Less 文件编译为 CSS 文件 // 失败的
}
- 引入stylus
安装
yarn add stylus stylus-loader --dev
再改config.js
{
test: /\.styl$/i,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
sourceMap: true,
},
},
{
loader: 'stylus-loader',
options: {
sourceMap: true,
},
},
],
},