webpack4发布以来,我写项目都是用脚手架,即便再简单的项目,真的是really shame。。虽然道听途说了不少 webpack4 的特性,却没有尝试过,由于它给人的感受就是,em...很难。可是今天我从最简单的部分开始,一点点搭建起一个项目。css
让咱们从0开始,新建一个项目,在终端执行如下语句:html
mkdir webpack-4-quickstart && cd webpack-4-quickstart
npm init -y
npm i webpack --save-dev
npm i webpack-cli --save-dev
复制代码
修改代码 package.json
中 scripts
部分:vue
"scripts": {
"build": "webpack"
}
复制代码
如今,咱们的 package.json
是这样的:node
{
"name": "webpack-4-quickstart",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^4.14.0",
"webpack-cli": "^3.0.8"
}
}
复制代码
此时,咱们执行 npm run build
, 会给出如下提示/错误:react
mode
选项为了解决第一个问题,咱们尝试新建 src/index.js
:webpack
console.log(`I'm a entry point`);
复制代码
此时再次执行 npm run build
,成功打包出了 dist/main.js
,所以咱们能够得知:git
webpack4 more配置了 entry(入口)
src/index.js
和output(出口)dist/main.js
github
固然,若是你想覆盖这个配置(好比修改成 ./foo/src/js/index.js
),能够在 package.json
修改:web
"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"
}
复制代码
webpack4 以前,咱们写一个项目起码会设置两种类型文件:vue-cli
而 webpack4 的 mode
给出了两种配置:development
和 production
。
咱们修改 package.json
中 scripts
部分:
"scripts": {
"dev": "webpack --mode development",
"build": "webpack --mode production"
}
复制代码
咱们分别执行 npm run dev
和 npm run build
执行 npm run dev
打包的是未压缩的代码,而 npm run build
是压缩后的代码。
- 生产模式下:启用了 代码压缩、做用域提高(scope hoisting)、 tree-shaking,使代码最精简
- 开发模式下:相较于更小体积的代码,提供的是打包速度上的优化
webpack 4 的零配置主要应用于:
entry
默认设置为 ./src/index.js
output
默认设置为 ./dist/main.js
production
和 development
两种模式项目搭建,咱们对webpack的诉求是:
用 babel 转换 ES6 代码须要使用到 babel-loader ,咱们须要安装一系列的依赖:
npm i babel-core babel-loader babel-preset-env --save-dev
复制代码
而后在根目录新建一个babel配置文件 .babelrc
:
{
"presets": [
"env"
]
}
复制代码
那么如何将配置用于webpack打包中?
--module-bind
使用 webpack 的配置文件的方法:
新建 webpack.config.js
:
module.exports = {
module: {
rules: [
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
}
]
}
}
复制代码
在 npm scripts 中配置的方法:
"scripts": {
"dev": "webpack --mode development --module-bind js=babel-loader",
"build": "webpack --mode production --module-bind js=babel-loader"
}
复制代码
然而浏览器依然不支持一些语法的使用,致使兼容性问题,咱们用 babel-polyfill
解决:
npm i babel-polyfill babel-plugin-transform-runtime --save-dev
复制代码
.babelrc
添加配置:
{
"presets": [
"env"
],
"plugins": [
"transform-runtime"
]
}
复制代码
最后在 webpack.config.js
中将 babel-polyfill
加到你的 entry 数组中:
const path = require('path');
module.exports = {
entry: [
"babel-polyfill",
path.join(__dirname, './src/index.js')
],
// ...
};
复制代码
webpack 并不会主动将你的css代码提取到一个文件,过去咱们使用 extract-text-webpack-plugin
,在webpack4中咱们使用mini-css-extract-plugin来解决这个问题。
postcss-loader 用于添加浏览器前缀,相关配置我喜欢在根目录新建 postcss.config.js
配置
npm i mini-css-extract-plugin css-loader --save-dev
npm i style-loader postcss-loader --save-dev
复制代码
// webpack.config.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = (env, argv) => {
const devMode = argv.mode !== 'production'
return {
module: {
rules: [
// ...,
{
test: /\.css$/,
use: [
devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader'
]
},
]
},
plugins: [
// ...,
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
]
}
}
复制代码
// postcss.config.js
module.exports = {
plugins: {
autoprefixer: {}
}
}
复制代码
npm i html-webpack-plugin html-loader --save-dev
复制代码
// webpack.config.js
const HtmlWebPackPlugin = require("html-webpack-plugin");
module.exports = {
module: {
rules: [
// ...,
{
test: /\.html$/,
use: [{
loader: "html-loader",
options: {
minimize: true
}
}]
}
]
},
plugins: [
new HtmlWebPackPlugin({
template: "./src/index.html",
filename: "./index.html"
})
]
};
复制代码
每次打包,都会生成项目的静态资源,随着某些文件的增删,咱们的 dist 目录下可能产生一些再也不使用的静态资源,webpack并不会自动判断哪些是须要的资源,为了避免让这些旧文件也部署到生产环境上占用空间,因此在 webpack 打包前最好能清理 dist 目录。
npm install clean-webpack-plugin --save-dev
复制代码
const CleanWebpackPlugin = require('clean-webpack-plugin');
module.exports = {
plugins: [
new CleanWebpackPlugin(['dist']),
]
};
复制代码
npm install file-loader --save-dev
复制代码
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'file-loader',
options: {}
}
]
}
]
}
}
复制代码
npm i webpack-dev-server --save-dev
复制代码
package.json
"scripts": {
"start": "webpack-dev-server --mode development --open",
"build": "webpack --mode production"
}
复制代码
如今咱们模仿 create-react-app 的结构,本身搭建一个 react 项目,而且用less预编译:
├── public
│ └── index.html # html 模板
├── src
│ ├── assets # 静态资源
│ │ └── logo.png
│ ├── components # 组件
│ │ └── App.js
│ ├── index.js # 入口文件
│ └── styles
│ └── index.less
├── .babelrc
├── package-lock.json
├── package.json
├── postcss.config.js
└── webpack.config.js
复制代码
在以上的基础(项目搭建部分),再安装react相关模块及less模块:
npm i react react-dom --save
npm i babel-preset-react --save-dev
npm i less less-loader --save-dev
复制代码
修改 .babelrc
:
{
"presets": ["env", "react"]
}
复制代码
修改 webpack.config.js
:
// webpack.config.js
const path = require('path');
module.exports = (env, argv) => {
const devMode = argv.mode !== 'production'
return {
entry: [
"babel-polyfill",
path.join(__dirname, './src/index.js')
],
devServer: {
port: 3000, //端口号
},
module: {
rules: [
// ...
// 处理react
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
// 处理less
{
test: /\.less$/,
use: [
devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'less-loader',
]
}
]
}
}
};
复制代码
基本上搭建完这个项目了,若是你想看完整代码
一样地,咱们模仿 vue-cli 的结构,本身搭建一个 vue 项目,此次咱们的css预编译语言用 scss
:
├── public
│ └── index.html # html 模板
├── src
│ ├── assets # 静态资源
│ │ └── logo.png
│ ├── components # 组件
│ │ └── App.vue
│ ├── main.js # 入口文件
│ ├── main.js # 入口文件
│ └── styles
│ └── index.scss
├── .babelrc
├── package-lock.json
├── package.json
├── postcss.config.js
└── webpack.config.js
复制代码
在以上的基础(项目搭建部分),再安装vue相关模块及sass模块:
npm i vue --save
npm i vue-loader vue-template-compiler --save-dev
npm i node-sass sass-loader --save-dev
复制代码
// webpack.config.js
const path = require('path');
const VueLoaderPlugin = require('vue-loader/lib/plugin')
module.exports = (env, argv) => {
const devMode = argv.mode !== 'production'
return {
entry: [
"babel-polyfill",
path.join(__dirname, './src/main.js')
],
module: {
rules: [
// ...
// 解析vue
{
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {}
}
},
// 处理scss
{
test: /\.scss$/,
use: [
devMode ? 'style-loader' : MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader',
'sass-loader',
]
}
]
},
plugins: [
// ...
new VueLoaderPlugin()
]
}
};
复制代码
一个简易的 vue-cli 也搭建完成,若是你想看完整代码