2-1
究竟是什么
最原始的网页开发方式
- index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>这是最原始的网页开发方式</title>
</head>
<body>
<p>这是我们的网页内容</p>
<div id="root"></div>
<script src="./index.js"></script>
</body>
</html>
- index.js
var dom = document.getElementById('root')
var header = document.createElement('div')
header.innerText = 'header'
dom.append(header)
var siderbar = document.createElement('div')
siderbar.innerText = 'siderbar'
dom.append(siderbar)
var content = document.createElement('div')
content.innerText = 'content'
dom.append(content)
-
测试
面向对象的开发方式
- index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>这是面向对象的开发方式</title>
</head>
<body>
<p>这是我们的网页内容</p>
<div id="root"></div>
<script src="./header.js"></script>
<script src="./siderbar.js"></script>
<script src="./content.js"></script>
<script src="./index.js"></script>
</body>
</html>
- header.js
function Header() {
var header = document.createElement('div')
header.innerText = 'header'
dom.append(header)
}
- sidebar.js
function Sidebar() {
var siderbar = document.createElement('div')
siderbar.innerText = 'siderbar'
dom.append(siderbar)
}
- content.js
function Content() {
var content = document.createElement('div')
content.innerText = 'content'
dom.append(content)
}
- index.js
var dom = document.getElementById('root')
new Header()
new Sidebar()
new Content()
-
测试
模块化的开发方式(webpack)
cd lesson
npm init -y
npm install webpack-cli webpack --save-dev
> fsevents@1.2.11 install /Users/wutianyu/Desktop/lesson/node_modules/fsevents
> node-gyp rebuild
SOLINK_MODULE(target) Release/.node
CXX(target) Release/obj.target/fse/fsevents.o
SOLINK_MODULE(target) Release/fse.node
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN lesson@1.0.0 No description
npm WARN lesson@1.0.0 No repository field.
+ webpack-cli@3.3.10
+ webpack@4.41.4
added 457 packages from 236 contributors in 15.191s
npx webpack index.js
- 此命令新增了 webpack 翻译出来的文件,默认位置:./dist/main.js
上面模块化里面用到的文件,在下面👇统一列出
- index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模块化的开发方式</title>
</head>
<body>
<p>这是我们的网页内容</p>
<div id="root"></div>
<script src="./dist/main.js"></script>
</body>
</html>
- index.js
import Header from './header.js'
import Sidebar from './siderbar.js'
import Content from './content.js'
new Header()
new Sidebar()
new Content()
- header.js
function Header() {
var dom = document.getElementById('root')
var header = document.createElement('div')
header.innerText = 'header'
dom.append(header)
}
export default Header
- sidebar.js
function Sidebar() {
var dom = document.getElementById('root')
var siderbar = document.createElement('div')
siderbar.innerText = 'siderbar'
dom.append(siderbar)
}
export default Sidebar
- content.js
function Content() {
var dom = document.getElementById('root')
var content = document.createElement('div')
content.innerText = 'content'
dom.append(content)
}
export default Content
-
测试
2-2
是什么
- 模块打包工具:bundler
- webpack 支持下面所有的模块引入规范
ES Module
CommonJS
CMD
ADM
CommonJS 示例
npm install --save-dev @types/node
- index.js
-import Header from './header.js'
-import Sidebar from './siderbar.js'
-import Content from './content.js'
+var Header = require('./header.js')
+var Sidebar = require('./siderbar.js')
+var Content = require('./content.js')
// ...
- header.js
// ...
-export default Header
+module.exports = Header
- sidebar.js
// ...
-export default Sidebar
+module.exports = Sidebar
- content.js
// ...
-export default Content
+module.exports = Content
作业:读文档
2-3
安装 Node.js
mkdir webpack-demo
cd webpack-demo
- npm init
- package.json
{
"name": "webpack-demo",
"version": "1.0.0",
"description": "",
"private": true,
"scripts": {},
"author": "Mark",
"license": "ISC"
}
安装 webpack
全局安装和卸载
npm install webpack-cli webpack -g
-
npm uninstall webpack-cli webpack -g
项目内安装 cd webpack-demo
npm install webpack-cli webpack --save-dev
npx webpack -v
- 查看可用版本
npm info webpack
2-4
使用默认配置文件
- webpack.config.js
const path = require('path')
module.exports = {
entry: './index.js',
output: {
path: path.resolve(__dirname, 'bundle'),
filename: 'bundle.js'
}
}
不用再手动指定文件路径
npx webpack
自己配置的,要手动指定
npx webpack --config webpack.my.js
重整文件目录结构
- webpack.config.js
const path = require('path')
module.exports = {
- entry: './index.js',
+ entry: './src/index.js',
output: {
- path: path.resolve(__dirname, 'bundle'),
+ path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
}
}
npx webpack
- package.json
{
"name": "lesson",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
+ "bundle": "webpack"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@types/node": "^12.12.21",
"webpack": "^4.41.4",
"webpack-cli": "^3.3.10"
}
}
-
npm run bundle
=npx webpack
- ./index.html 移动到 ./dist/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>模块化的开发方式</title>
</head>
<body>
<p>这是我们的网页内容</p>
<div id="root"></div>
- <script src="./dist/main.js"></script>
+ <script src="./bundle.js"></script>
</body>
</html>
-
测试
三种运行 webpack 的方式
webpack index.js
npx webpack index.js
npm run bundle -> webpack
作业:读文档
2-5
输出信息讲解
npm run bundle
> lesson@1.0.0 bundle /Users/wutianyu/Desktop/lesson
> webpack
Hash: 64df8628023b23900853
Version: webpack 4.41.4
Time: 70ms
Built at: 2019-12-20 17:14:17
Asset Size Chunks Chunk Names
bundle.js 1.36 KiB 0 [emitted] main
Entrypoint main = bundle.js
[0] ./src/index.js 154 bytes {0} [built]
[1] ./src/header.js 186 bytes {0} [built]
[2] ./src/siderbar.js 196 bytes {0} [built]
[3] ./src/content.js 192 bytes {0} [built]
const path = require('path')
module.exports = {
+ mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'file-loader'
}
}]
}
}
3-1
Loader 是什么
可以加载图片的 file-loader
npm install file-loader -D
- ./src/index.js
var Header = require('./header.js')
var Sidebar = require('./siderbar.js')
var Content = require('./content.js')
+var avatar = require('./avatar.jpg')
+console.log(avatar)
new Header()
new Sidebar()
new Content()
const path = require('path')
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
+ module: {
+ rules: [{
+ test: /\.(png|jpg|gif)$/,
+ use: {
+ loader: 'file-loader'
+ }
+ }]
+ }
}
npm run bundle
- ./dist/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>file-loader</title>
</head>
<body>
<div id="root"></div>
<script src="./bundle.js"></script>
</body>
</html>
-
测试
- 删除 ./src/header.js && ./src/sidebar.js && ./src/content.js
- ./src/index.js
import avatar from './avatar.jpg'
var img = new Image()
img.src = avatar
var root = document.getElementById('root')
root.append(img)
npm run bundle
-
测试
3-2
打包的图片,路径和名字不变
npm run bundle
const path = require('path')
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'file-loader',
+ options: {
+ name: '[path][name].[ext]'
+ }
}
}]
}
}
打包的图片,改变路径为 images
const path = require('path')
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'file-loader',
options: {
- name: '[path][name].[ext]'
+ name: '[name].[ext]',
+ outputPath: 'images/'
}
}
}]
}
}
打包图片的另一种 loader
npm install url-loader -D
- 最佳实践:2k以下,base64,节省一个请求
const path = require('path')
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [{
test: /\.(png|jpg|gif)$/,
use: {
- loader: 'file-loader',
+ loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
+ limit: 2048
}
}
}]
}
}
npm run bundle
作业:读文档
3-3
样式处理
- ./src/index.css
.avatar {
width: 150px;
height: 150px;
}
- ./src/index.js
import avatar from './avatar.jpg'
+import './index.css'
var img = new Image()
img.src = avatar
+img.classList.add('avatar')
var root = document.getElementById('root')
root.append(img)
npm install style-loader css-loader -D
const path = require('path')
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048
}
}
+ },{
+ test: /\.css$/,
+ use: ['style-loader', 'css-loader']
+ }]
}
}
npm run bundle
-
测试
下面的引入用相同的效果
- ./src/index.css
-.avatar {
- width: 150px;
- height: 150px;
-}
+@import './avatar.css'
- ./src/avatar.css
+.avatar {
+ width: 150px;
+ height: 150px;
+}
处理 sass
avatar.css-
index.css-> index.scss
-@import './avatar.css'
+body {
+ .avatar {
+ width: 150px;
+ height: 150px;
+ }
+}
- index.js
import avatar from './avatar.jpg'
-import './index.css'
+import './index.scss'
var img = new Image()
img.src = avatar
img.classList.add('avatar')
var root = document.getElementById('root')
root.append(img)
- webpack.config.js
const path = require('path')
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048
}
}
},{
- test: /\.css$/,
+ test: /\.scss$/,
- use: ['style-loader', 'css-loader']
+ use: ['style-loader', 'css-loader', 'sass-loader']
}]
}
}
npm install sass-loader node-sass --save-dev
npm run bundle
-
测试
处理浏览器厂商前缀
- index.scss
body {
.avatar {
width: 150px;
height: 150px;
+ transform: translate(100px, 100px);
}
}
- webpack.config.js
const path = require('path')
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048
}
}
},{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'sass-loader',
+ 'postcss-loader'
]
}]
}
}
npm i -D postcss-loader
npm install autoprefixer -D
- postcss.config.js
module.exports = {
plugins: [
require('autoprefixer')
]
}
npm run bundle
-
测试
3-4
对 .scss 引用 .scss 的多级引用处理
- webpack.config.js
const path = require('path')
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048
}
}
},{
test: /\.scss$/,
use: [
'style-loader',
- 'css-loader',
+ {
+ loader: 'css-loader',
+ options: {
+ importLoaders: 2
+ }
+ },
'sass-loader',
'postcss-loader'
]
}]
}
}
实现 CSS module,避免全局污染
- webpack.config.js
const path = require('path')
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048
}
}
},{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
+ modules: true
}
},
'sass-loader',
'postcss-loader'
]
}]
}
}
- createAvatar.js
import avatar from './avatar.jpg'
function createAvatar() {
var img = new Image()
img.src = avatar
img.classList.add('avatar')
var root = document.getElementById('root')
root.append(img)
}
export default createAvatar
- index.js
import avatar from './avatar.jpg'
-import './index.scss'
+import style from './index.scss'
import createAvatar from './createAvatar'
createAvatar()
var img = new Image()
img.src = avatar
-img.classList.add('avatar')
+img.classList.add(style.avatar)
var root = document.getElementById('root')
root.append(img)
npm run bundle
-
测试
需要样式,主动引用,生效
- createAvatar.js
import avatar from './avatar.jpg'
+import style from './index.scss'
function createAvatar() {
var img = new Image()
img.src = avatar
- img.classList.add('avatar')
+ img.classList.add(style.avatar)
var root = document.getElementById('root')
root.append(img)
}
export default createAvatar
npm run bundle
-
测试
处理字体文件
src/createAvatar.jssrc/avatar.jpgsrc/index.jssrc/index.scss- 打开 iconfont
- src/font/iconfont.eot
- src/font/iconfont.svg
- src/font/iconfont.ttf
- src/font/iconfont.woff
- src/font/iconfont.woff2
- src/index.scss
@font-face {
font-family: "iconfont";
src: url('./font/iconfont.eot?t=1576845174515'); /* IE9 */
src: url('./font/iconfont.eot?t=1576845174515#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAPEAAsAAAAAB8wAAAN1AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDHAqDCIJuATYCJAMQCwoABCAFhG0HSBvgBsiOkVscy/LL/yeCai179vZp/wOoQDFYLh+V8gQuSiRGx5gYn/IEwv1Pv60ejluwHVzVVoRsFOKAaCPX/RtV9T+HS5vi81uWyxyTo16A8dbAxh4gARfICfothzOvwqNrM4FiQm/EYX5pLTjKSK9A3IkCC44phVyTHppCvWRihngEO800UXEGwIP/+/iC6HAESa0CMvDoIk8Dma/Us3g04v8IzS4CmOPpIE6jwiKQiatSwwkUBhYhRW+utA00NSXGqvN5Fv//P2btRdCk//IIlUTUgaR2wCYOVrxSNpng1YevTBgPKRK8kAlNtHAPPAGRjI2zeJY6zkpHRx/KzZ+7dk11/Tpz9WrdlSutjFcb0JIPu3ZtoKpXnRupcq4l9VRD47RQco5/PbubmgxQgjxATjpHjGSYkf6BqXVbVsCIldTkwwTBMEIEM3IkqZo2BWqHNXUzOrsHLDkV6Ns0K0jwY2av3r61S93Oq73Pd16Mbt1CTvSSWzcXK5coYQBaghbfurXkwVR0/LhiKqVC1lQ0DR07jqYCFT7Ti4u+tbP+1g44wBdc7J57Ebv+V+dc06VX1Cmy1WL6deXvdJt8NDGCsMsKN/dQiS4tVElm8pNWRj4d4PM7sMvHLqHw13meRbF/cmwjoSAmlIN7hM/2Cnh+f+LmotuzrduCB/v5U76bA18UxTQu/K7rGzC+LN+nPA8sAN0raAvq7eP/owMIQiOrBjT01/2N/34tM9rcUr86UkqAl44P+oGtOzJDOyG8f2Zr5o9itszLBpsoc9Y4NsM0ZquJXhKKgt8TYdC9MUQjrVMJTSMxJA3jUGmaRGbsItS0bUJd0w4UCwqmtw2RIJGdgHljEYR+6yHp9QyVfmeRGXsXaka9hbr+QFAch9eCbdMhkjkSZmWsodUDaZEzm3imlskgvRoLfQ2slGT7OBWWbKKbjgqPzIYLsAlLYwyx9ROiZZmneclspPPRdthgMNMWyazDnByulWVLckQEX/amcM5sBNIBCcaSYRo0tYFoIo6ZCe8Wl5G571fDBH0ZsKSanDqlCiaxERunRQkX2QJZIDC1yrmWa2z6EUSTyXg0nsTMiJaPdJiBBsxolvJ2OhhHFk7bw2eRLAIX4tsKwucXGZ9wCRRkkRwKAhFKwg7KBWsSNKxOdO2KLNb5Flr04bSY04smAAAAAA==') format('woff2'),
url('./font/iconfont.woff?t=1576845174515') format('woff'),
url('./font/iconfont.ttf?t=1576845174515') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
url('./font/iconfont.svg?t=1576845174515#iconfont') format('svg'); /* iOS 4.1- */
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.iconfangdajing:before {
content: "\e60b";
}
.iconAa:before {
content: "\e636";
}
.iconicon-checkin:before {
content: "\e615";
}
- src/index.js
var root = document.getElementById('root')
import './index.scss'
root.innerHTML = '<div class="iconfont iconfangdajing"></div>'
- webpack.config.js
const path = require('path')
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048
}
}
},{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
- modules: true
}
},
'sass-loader',
'postcss-loader'
]
+ },{
+ test: /\.(eot|ttf|svg|woff)$/,
+ use: {
+ loader: 'file-loader',
+ }
+ }]
}
}
npm run bundle
-
测试
作业:读文档
3-5 plugins
自动生成 html
npm install -D html-webpack-plugin
npm run bundle
- webpack.config.js
const path = require('path')
+var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048
}
}
},{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
'sass-loader',
'postcss-loader'
]
},{
test: /\.(eot|ttf|svg|woff)$/,
use: {
loader: 'file-loader',
}
}]
},
+ plugins: [new HtmlWebpackPlugin({
+ template: 'src/index.html'
+ })]
}
npm run bundle
-
测试
每次打包都先清空上一次的
npm install clean-webpack-plugin -D
- webpack.config.js
const path = require('path')
var HtmlWebpackPlugin = require('html-webpack-plugin');
+var { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
mode: 'development',
entry: './src/index.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
module: {
rules: [{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048
}
}
},{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
'sass-loader',
'postcss-loader'
]
},{
test: /\.(eot|ttf|svg|woff)$/,
use: {
loader: 'file-loader',
}
}]
},
plugins: [new HtmlWebpackPlugin({
template: 'src/index.html'
+ }), new CleanWebpackPlugin()]
}
3-6 输入和输出
- webpack.config.js
const path = require('path')
var HtmlWebpackPlugin = require('html-webpack-plugin');
var { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
mode: 'development',
- // entry: './src/index.js',
+ entry: {
main: './src/index.js',
sub: './src/index.js'
},
output: {
publicPath: 'https://cdn.com.cn',
path: path.resolve(__dirname, 'dist'),
- // filename: 'bundle.js'
+ filename: '[name].js'
},
module: {
rules: [{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048
}
}
},{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
'sass-loader',
'postcss-loader'
]
},{
test: /\.(eot|ttf|svg|woff)$/,
use: {
loader: 'file-loader',
}
}]
},
plugins: [new HtmlWebpackPlugin({
template: 'src/index.html'
}), new CleanWebpackPlugin()]
}
3-7 SourceMap 的配置
删除
./src/font./src/index.scss./src/index.js- ./src/index.js
console.log('Hello, World!');
- webpack.config.js
const path = require('path')
var HtmlWebpackPlugin = require('html-webpack-plugin');
var { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
mode: 'development',
+ development devtool: 'cheap-module-eval-source-map',
+ production devtool: 'cheap-module-source-map',
entry: {
main: './src/index.js',
- // sub: './src/index.js'
},
output: {
- // publicPath: 'https://cdn.com.cn',
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
module: {
rules: [{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048
}
}
},{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
'sass-loader',
'postcss-loader'
]
},{
test: /\.(eot|ttf|svg|woff)$/,
use: {
loader: 'file-loader',
}
}]
},
plugins: [new HtmlWebpackPlugin({
template: 'src/index.html'
}), new CleanWebpackPlugin()]
}
npm run bundle
作业:读文档
3-8 webpack-dev-server
npm install webpack-dev-server -D
- webpack.config.js
const path = require('path')
var HtmlWebpackPlugin = require('html-webpack-plugin');
var { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
mode: 'development',
devtool: 'cheap-module-eval-source-map',
entry: {
main: './src/index.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
module: {
rules: [{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048
}
}
},{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
'sass-loader',
'postcss-loader'
]
},{
test: /\.(eot|ttf|svg|woff)$/,
use: {
loader: 'file-loader',
}
}]
},
plugins: [new HtmlWebpackPlugin({
template: 'src/index.html'
}), new CleanWebpackPlugin()],
+ devServer: {
+ contentBase: './dist',
+ open: true,
+ proxy: {
+ '/api': 'http://localhost:8000'
+ }
+ }
}
- package.json
{
"name": "lesson",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
- "bundle": "webpack",
+ "watch": "webpack --watch",
+ "start": "webpack-dev-server",
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@types/node": "^12.12.21",
"autoprefixer": "^9.7.3",
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^3.4.0",
"file-loader": "^5.0.2",
"html-webpack-plugin": "^3.2.0",
"node-sass": "^4.13.0",
"postcss-loader": "^3.0.0",
"sass-loader": "^8.0.0",
"style-loader": "^1.0.2",
"url-loader": "^3.0.0",
"webpack": "^4.41.4",
"webpack-cli": "^3.3.10",
"webpack-dev-server": "^3.10.1"
}
}
npm run start
扩展内容(自建服务器)
npm install express webpack-dev-middleware -D
- package.json
{
"name": "lesson",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"bundle": "webpack",
"watch": "webpack --watch",
"start": "webpack-dev-server",
+ "server": "node server.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@types/node": "^12.12.21",
"autoprefixer": "^9.7.3",
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^3.4.0",
"file-loader": "^5.0.2",
"html-webpack-plugin": "^3.2.0",
"node-sass": "^4.13.0",
"postcss-loader": "^3.0.0",
"sass-loader": "^8.0.0",
"style-loader": "^1.0.2",
"url-loader": "^3.0.0",
"webpack": "^4.41.4",
"webpack-cli": "^3.3.10",
"webpack-dev-server": "^3.10.1"
}
}
- server.js
const express = require('express')
const webpack = require('webpack')
const webpackDevMiddleware = require('webpack-dev-middleware')
const config = require('./webpack.config.js')
const complier = webpack(config)
const app = express()
app.use(webpackDevMiddleware(complier, {}))
app.listen(3000, () => {
console.log('server is running...')
})
作业
3-9 & 3-10
热更新 css
server.js- webpack.config.js
const path = require('path')
var HtmlWebpackPlugin = require('html-webpack-plugin');
var { CleanWebpackPlugin } = require('clean-webpack-plugin')
+var webpack = require('webpack')
module.exports = {
mode: 'development',
devtool: 'cheap-module-eval-source-map',
entry: {
main: './src/index.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
module: {
rules: [{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048
}
}
+ },{
+ test: /\.css$/,
+ use: [
+ 'style-loader',
+ 'css-loader',
+ 'postcss-loader'
+ ]
+ },{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
'sass-loader',
'postcss-loader'
]
},{
test: /\.(eot|ttf|svg|woff)$/,
use: {
loader: 'file-loader',
}
}]
},
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html'
}),
new CleanWebpackPlugin(),
+ new webpack.HotModuleReplacementPlugin()
],
devServer: {
contentBase: './dist',
open: true,
port: 8080,
+ hot: true,
+ hotOnly: true,
- proxy: {
- '/api': 'http://localhost:8000'
- }
}
}
- package.json
{
"name": "lesson",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
- "bundle": "webpack",
- "watch": "webpack --watch",
+ "start": "webpack-dev-server",
- "server": "node server.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@types/node": "^12.12.21",
"autoprefixer": "^9.7.3",
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^3.4.0",
"express": "^4.17.1",
"file-loader": "^5.0.2",
"html-webpack-plugin": "^3.2.0",
"node-sass": "^4.13.0",
"postcss-loader": "^3.0.0",
"sass-loader": "^8.0.0",
"style-loader": "^1.0.2",
"url-loader": "^3.0.0",
"webpack": "^4.41.4",
"webpack-cli": "^3.3.10",
"webpack-dev-middleware": "^3.7.2",
"webpack-dev-server": "^3.10.1"
}
}
- ./src/index.js
import './style.css'
var btn = document.createElement('button')
btn.innerHTML = '新增'
document.body.appendChild(btn)
btn.onclick = function () {
var div = document.createElement('div')
div.innerHTML = 'item'
document.body.appendChild(div)
}
- ./src/style.css
div:nth-of-type(odd) {
background: blue;
}
npm run start
热更新 js
- ./src/counter.js
function counter() {
var div = document.createElement('div')
div.setAttribute('id', 'counter')
div.innerHTML = 1;
div.onclick = function () {
div.innerHTML = parseInt(div.innerHTML, 10) + 1
}
document.body.appendChild(div)
}
export default counter
- number.js
function number() {
var div = document.createElement('div')
div.setAttribute('id', 'number')
div.innerHTML = 3000
document.body.appendChild(div)
}
export default number
./src/index.js- ./src/index.js
import counter from './counter'
import number from './number'
counter()
number()
if (module.hot) {
module.hot.accept('./number', () => {
document.body.removeChild(document.getElementById('number'))
number()
})
}
作业:读文档
3-11
./src/counter.js./src/number.js./src/style.css./src/index.js- ./src/index.js
const arr = [
new Promise(() => {}),
new Promise(() => {})
]
arr.map(item => {
console.log(item)
})
- webpack.config.js
const path = require('path')
var HtmlWebpackPlugin = require('html-webpack-plugin');
var { CleanWebpackPlugin } = require('clean-webpack-plugin')
var webpack = require('webpack')
module.exports = {
mode: 'development',
devtool: 'cheap-module-eval-source-map',
entry: {
main: './src/index.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
module: {
rules: [{
+ test: /\.js$/,
+ exclude: /node_modules/,
+ loader: "babel-loader",
+ options: {
+ "presets": [['@babel/preset-env', {
+ corejs: '2.6.11',
+ useBuiltIns: 'usage'
+ }]]
+ }
},{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048
}
}
},{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
'postcss-loader'
]
},{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
'sass-loader',
'postcss-loader'
]
},{
test: /\.(eot|ttf|svg|woff)$/,
use: {
loader: 'file-loader',
}
}]
},
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html'
}),
new CleanWebpackPlugin(),
new webpack.HotModuleReplacementPlugin()
],
devServer: {
contentBase: './dist',
open: true,
port: 8080,
hot: true,
hotOnly: true,
}
}
npm install --save-dev babel-loader @babel/core
npm install @babel/preset-env --save-dev
npm install --save @babel/polyfill
npx webpack
- babel官网
打包组件库
npm install --save-dev @babel/plugin-transform-runtime
npm install --save @babel/runtime
npm install --save @babel/runtime-corejs2
- .babelrc(options)
{
"plugins": [["@babel/plugin-transform-runtime", {
// "absoluteRuntime": false,
"corejs": 2,
"helpers": true,
"regenerator": true,
"useESModules": false,
// "version": "7.0.0-beta.0"
}]]
}
3-13
npm install react react-dom --save
npm install --save-dev @babel/preset-react
./src/index.js- ./src/index.js
import React, { Component } from 'react'
import ReactDom from 'react-dom'
class App extends Component {
render() {
return (
<div>Hello World!</div>
)
}
}
ReactDom.render(<App />, document.getElementById('root'))
- webpack.config.js
const path = require('path')
var HtmlWebpackPlugin = require('html-webpack-plugin');
var { CleanWebpackPlugin } = require('clean-webpack-plugin')
var webpack = require('webpack')
module.exports = {
mode: 'development',
devtool: 'cheap-module-eval-source-map',
entry: {
main: './src/index.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
// - options: {
// - "presets": [['@babel/preset-env', {
// - corejs: '2.6.11',
// - useBuiltIns: 'usage'
// - }]]
// - }
},{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048
}
}
},{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
'postcss-loader'
]
},{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
'sass-loader',
'postcss-loader'
]
},{
test: /\.(eot|ttf|svg|woff)$/,
use: {
loader: 'file-loader',
}
}]
},
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html'
}),
new CleanWebpackPlugin(),
new webpack.HotModuleReplacementPlugin()
],
devServer: {
contentBase: './dist',
open: true,
port: 8080,
hot: true,
hotOnly: true
}
}
- .babelrc
{
"presets": [
[
"@babel/preset-env", {
"corejs": "2.6.11",
"useBuiltIns": "usage"
}
],
"@babel/preset-react"
]
}
react 热加载(webpack)
- ./src/index.js
import React from 'react'
import ReactDOM from 'react-dom'
import App from './App'
const rootEl = document.getElementById("root")
ReactDOM.render(
<App />,
rootEl
)
if(module.hot) {
module.hot.accept("./App", () => {
const App = require("./App").default;
ReactDOM.render(
<App />,
rootEl
)
})
}
- ./src/app.js
import React, { Component } from 'react'
class App extends Component {
render() {
return (
<div>Hello World</div>
)
}
}
export default App
没有测试通过
npm install react-hot-loadernpm install @types/react
4-1 Tree Shaking
只有引用的方法会被打包(生产)
./src/index.js- ./src/index.js
import { add } from './math.js'
add(1, 2)
- ./src/math.js
export const add = (a, b) => {
console.log(a + b);
}
export const minus = (a, b) => {
console.log(a - b);
}
- package.json
{
"name": "lesson",
+ "sideEffects": false,
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "webpack-dev-server"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.7.7",
"@babel/preset-env": "^7.7.7",
"@babel/preset-react": "^7.7.4",
"@types/node": "^12.12.21",
"autoprefixer": "^9.7.3",
"babel-loader": "^8.0.6",
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^3.4.0",
"express": "^4.17.1",
"file-loader": "^5.0.2",
"html-webpack-plugin": "^3.2.0",
"node-sass": "^4.13.0",
"postcss-loader": "^3.0.0",
"sass-loader": "^8.0.0",
"style-loader": "^1.0.2",
"url-loader": "^3.0.0",
"webpack": "^4.41.4",
"webpack-cli": "^3.3.10",
"webpack-dev-middleware": "^3.7.2",
"webpack-dev-server": "^3.10.1"
},
"dependencies": {
"@babel/polyfill": "^7.7.0",
"react": "^16.12.0",
"react-dom": "^16.12.0"
}
}
- webpack.config.js
const path = require('path')
var HtmlWebpackPlugin = require('html-webpack-plugin');
var { CleanWebpackPlugin } = require('clean-webpack-plugin')
var webpack = require('webpack')
module.exports = {
- mode: 'development',
+ mode: 'production',
- devtool: 'cheap-module-eval-source-map',
+ devtool: 'cheap-module-source-map',
entry: {
main: './src/index.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048
}
}
},{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
'postcss-loader'
]
},{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
'sass-loader',
'postcss-loader'
]
},{
test: /\.(eot|ttf|svg|woff)$/,
use: {
loader: 'file-loader',
}
}]
},
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html'
}),
new CleanWebpackPlugin(),
new webpack.HotModuleReplacementPlugin()
],
devServer: {
contentBase: './dist',
open: true,
port: 8080,
hot: true,
hotOnly: true
},
- optimization: {
- usedExports: true
- }
}
4-2
将配置文件分成开发和线上
- webpack.prod.js
const path = require('path')
var HtmlWebpackPlugin = require('html-webpack-plugin');
var { CleanWebpackPlugin } = require('clean-webpack-plugin')
var webpack = require('webpack')
module.exports = {
- mode: 'development',
+ mode: 'production',
- devtool: 'cheap-module-eval-source-map',
+ devtool: 'cheap-module-source-map',
entry: {
main: './src/index.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048
}
}
},{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
'postcss-loader'
]
},{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
'sass-loader',
'postcss-loader'
]
},{
test: /\.(eot|ttf|svg|woff)$/,
use: {
loader: 'file-loader',
}
}]
},
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html'
}),
new CleanWebpackPlugin(),
- new webpack.HotModuleReplacementPlugin()
],
- devServer: {
- contentBase: './dist',
- open: true,
- port: 8080,
- hot: true,
- hotOnly: true
- },
- optimization: {
- usedExports: true
- }
}
- package.json
{
"name": "lesson",
"sideEffects": false,
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
- "start": "webpack-dev-server",
+ "dev": "webpack-dev-server --config webpack.dev.js",
+ "build": "webpack --config webpack.prod.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.7.7",
"@babel/preset-env": "^7.7.7",
"@babel/preset-react": "^7.7.4",
"@types/node": "^12.12.21",
"autoprefixer": "^9.7.3",
"babel-loader": "^8.0.6",
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^3.4.0",
"express": "^4.17.1",
"file-loader": "^5.0.2",
"html-webpack-plugin": "^3.2.0",
"node-sass": "^4.13.0",
"postcss-loader": "^3.0.0",
"sass-loader": "^8.0.0",
"style-loader": "^1.0.2",
"url-loader": "^3.0.0",
"webpack": "^4.41.4",
"webpack-cli": "^3.3.10",
"webpack-dev-middleware": "^3.7.2",
"webpack-dev-server": "^3.10.1"
},
"dependencies": {
"@babel/polyfill": "^7.7.0",
"react": "^16.12.0",
"react-dom": "^16.12.0"
}
}
- webpack.config.js
const path = require('path')
var HtmlWebpackPlugin = require('html-webpack-plugin');
var { CleanWebpackPlugin } = require('clean-webpack-plugin')
var webpack = require('webpack')
module.exports = {
mode: 'development',
devtool: 'cheap-module-eval-source-map',
entry: {
main: './src/index.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048
}
}
},{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
'postcss-loader'
]
},{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
'sass-loader',
'postcss-loader'
]
},{
test: /\.(eot|ttf|svg|woff)$/,
use: {
loader: 'file-loader',
}
}]
},
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html'
}),
new CleanWebpackPlugin(),
new webpack.HotModuleReplacementPlugin()
],
devServer: {
contentBase: './dist',
open: true,
port: 8080,
hot: true,
- hotOnly: true
},
optimization: {
usedExports: true
}
}
抽取公共部分
- npm install webpack-merge -D
- webpack.common.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
entry: {
main: './src/index.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js'
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048
}
}
},{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
'postcss-loader'
]
},{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
'sass-loader',
'postcss-loader'
]
},{
test: /\.(eot|ttf|svg|woff)$/,
use: {
loader: 'file-loader',
}
}]
},
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html'
}),
new CleanWebpackPlugin()
]
}
- webpack.dev.js
const webpack = require('webpack')
const merge = require('webpack-merge')
const commonConfig = require('./webpack.common.js')
const devConfig = {
mode: 'development',
devtool: 'cheap-module-eval-source-map',
plugins: [
new webpack.HotModuleReplacementPlugin()
],
devServer: {
contentBase: './dist',
open: true,
port: 8080,
hot: true
},
optimization: {
usedExports: true
}
}
module.exports = merge(commonConfig, devConfig)
- webpack.prod.js
const merge = require('webpack-merge')
const commonConfig = require('./webpack.common.js')
const prodConfig = {
mode: 'production',
devtool: 'cheap-module-source-map'
}
module.exports = merge(commonConfig, prodConfig)
4-3
- package.json
{
"name": "lesson",
"sideEffects": false,
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
- "dev": "webpack-dev-server --config webpack.dev.js",
- "build": "webpack --config webpack.prod.js"
+ "dev-build": "webpack --config ./build/webpack.dev.js",
+ "dev": "webpack-dev-server --config ./build/webpack.dev.js",
+ "build": "webpack --config ./build/webpack.prod.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.7.7",
"@babel/preset-env": "^7.7.7",
"@babel/preset-react": "^7.7.4",
"@types/node": "^12.12.21",
"autoprefixer": "^9.7.3",
"babel-loader": "^8.0.6",
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^3.4.0",
"express": "^4.17.1",
"file-loader": "^5.0.2",
"html-webpack-plugin": "^3.2.0",
"node-sass": "^4.13.0",
"postcss-loader": "^3.0.0",
"sass-loader": "^8.0.0",
"style-loader": "^1.0.2",
"url-loader": "^3.0.0",
"webpack": "^4.41.4",
"webpack-cli": "^3.3.10",
"webpack-dev-middleware": "^3.7.2",
"webpack-dev-server": "^3.10.1",
"webpack-merge": "^4.2.2"
},
"dependencies": {
"@babel/polyfill": "^7.7.0",
"react": "^16.12.0",
"react-dom": "^16.12.0"
}
}
- webpack.common.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
entry: {
main: './src/index.js',
},
output: {
- path: path.resolve(__dirname, 'dist'),
+ path: path.resolve(__dirname, '../dist'),
filename: '[name].js'
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048
}
}
},{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
'postcss-loader'
]
},{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
'sass-loader',
'postcss-loader'
]
},{
test: /\.(eot|ttf|svg|woff)$/,
use: {
loader: 'file-loader',
}
}]
},
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html'
}),
new CleanWebpackPlugin()
]
}
进入正题,代码拆分
npm install lodash --save
- ./build/webpack.common.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
entry: {
+ lodash: './src/lodash.js',
main: './src/index.js',
},
output: {
path: path.resolve(__dirname, '../dist'),
filename: '[name].js'
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048
}
}
},{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
'postcss-loader'
]
},{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
'sass-loader',
'postcss-loader'
]
},{
test: /\.(eot|ttf|svg|woff)$/,
use: {
loader: 'file-loader',
}
}]
},
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html'
}),
new CleanWebpackPlugin()
]
}
- ./src/loads.js
import _ from 'lodash'
window._ = _
- ./src/index.js
console.log(_.join(['a', 'b', 'c'], '***'))
同步加载,代码分割
./src/lodash.js./src/index.js- ./src/index.js
import _ from 'lodash'
console.log(_.join(['a', 'b', 'c'], '***'))
- webpack.common.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
entry: {
- lodash: './src/lodash.js',
main: './src/index.js',
},
output: {
path: path.resolve(__dirname, '../dist'),
filename: '[name].js'
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048
}
}
},{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
'postcss-loader'
]
},{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
'sass-loader',
'postcss-loader'
]
},{
test: /\.(eot|ttf|svg|woff)$/,
use: {
loader: 'file-loader',
}
}]
},
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html'
}),
new CleanWebpackPlugin()
],
+ optimization: {
+ splitChunks: {
+ chunks: 'all'
+ }
+ }
}
异步加载,代码分割
npm install babel-plugin-dynamic-import-webpack -D
- ./src/index.js
function getComponent() {
return import('lodash').then(({ default: _ }) => {
var element = document.createElement('div')
element.innerHTML = _.join(['Dell', 'Lee'], '_')
return element
})
}
getComponent().then(element => {
document.body.appendChild(element)
})
- .babelrc
{
"presets": [
[
"@babel/preset-env", {
"corejs": "2.6.11",
"useBuiltIns": "usage"
}
],
"@babel/preset-react"
],
+ "plugins": ["dynamic-import-webpack"]
}
4-5
改名
- npm install --save-dev @babel/plugin-syntax-dynamic-import
- ./src/index.js
function getComponent() {
return import(/* webpackChunkName:"lodash" */'lodash').then(({ default: _ }) => {
var element = document.createElement('div')
element.innerHTML = _.join(['Dell', 'Lee'], '_')
return element
})
}
getComponent().then(element => {
document.body.appendChild(element)
})
./babelrc
{
"presets": [
[
"@babel/preset-env", {
"corejs": "2.6.11",
"useBuiltIns": "usage"
}
],
"@babel/preset-react"
],
- "plugins": ["dynamic-import-webpack"]
+ "plugins": ["@babel/plugin-syntax-dynamic-import"]
}
- package.json
{
"name": "lesson",
"sideEffects": false,
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev-build": "webpack --config ./build/webpack.dev.js",
"dev": "webpack-dev-server --config ./build/webpack.dev.js",
"build": "webpack --config ./build/webpack.prod.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.7.7",
"@babel/preset-env": "^7.7.7",
"@babel/preset-react": "^7.7.4",
"@types/node": "^12.12.21",
"autoprefixer": "^9.7.3",
"babel-loader": "^8.0.6",
- "babel-plugin-dynamic-import-webpack": "^1.1.0",
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^3.4.0",
"express": "^4.17.1",
"file-loader": "^5.0.2",
"html-webpack-plugin": "^3.2.0",
"node-sass": "^4.13.0",
"postcss-loader": "^3.0.0",
"sass-loader": "^8.0.0",
"style-loader": "^1.0.2",
"url-loader": "^3.0.0",
"webpack": "^4.41.4",
"webpack-cli": "^3.3.10",
"webpack-dev-middleware": "^3.7.2",
"webpack-dev-server": "^3.10.1",
"webpack-merge": "^4.2.2"
},
"dependencies": {
"@babel/polyfill": "^7.7.0",
"lodash": "^4.17.15",
"react": "^16.12.0",
"react-dom": "^16.12.0"
}
}
- ./build/webpack.common.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
entry: {
main: './src/index.js',
},
output: {
path: path.resolve(__dirname, '../dist'),
filename: '[name].js'
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048
}
}
},{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
'postcss-loader'
]
},{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
'sass-loader',
'postcss-loader'
]
},{
test: /\.(eot|ttf|svg|woff)$/,
use: {
loader: 'file-loader',
}
}]
},
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html'
}),
new CleanWebpackPlugin()
],
optimization: {
splitChunks: {
chunks: 'all',
+ cacheGroups: {
+ vendors: false,
+ default: false
+ }
}
}
}
optimization: {
splitChunks: {
chunks: 'all',
minSize: 30000,// 超过 30K 分割
minChunks: 1,// 一个模块被引用几次才分割
maxAsyncRequests: 5,//同时加载的模块数最多5个
maxInitialRequests: 3,//首页引入的库最多3个
automaticNameDelimiter: '~',
name: true,//cacheGroups里的名字有效
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
filename: 'vendors.js'
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
filename: 'common.js'
}
}
}
}
- ./src/index.js
import _ from 'lodash'
var element = document.createElement('div')
element.innerHTML = _.join(['Dell', 'Lee'], '_')
document.body.appendChild(element)
// function getComponent() {
// return import(/* webpackChunkName:"lodash" */'lodash').then(({ default: _ }) => {
// var element = document.createElement('div')
// element.innerHTML = _.join(['Dell', 'Lee'], '_')
// return element
// })
// }
// getComponent().then(element => {
// document.body.appendChild(element)
// })
4-7
懒加载
- ./src/index.js
//- import _ from 'lodash'
//- var element = document.createElement('div')
//- element.innerHTML = _.join(['Dell', 'Lee'], '_')
//- document.body.appendChild(element)
// 懒加载主要是下面的promise import 方式
function getComponent() {
return import(/* webpackChunkName:"lodash" */'lodash').then(({ default: _ }) => {
var element = document.createElement('div')
element.innerHTML = _.join(['Dell', 'Lee'], '_')
return element
})
}
// 鼠标点击才加载 lodash 库
+document.addEventListener('click', () => {
+ getComponent().then(element => {
+ document.body.appendChild(element)
+ })
+})
//- getComponent().then(element => {
//- document.body.appendChild(element)
//- })
ES7 的语法改写
- ./src/index.js
async function getComponent() {
const { default: _ } = await import(/* webpackChunkName:"lodash" */'lodash')
const element = document.createElement('div')
element.innerHTML = _.join(['Dell', 'Lee'], '_')
return element
}
chunk 是什么
- 代码分割,默认即可
optimization: {
splitChunks: {
chunks: 'all'
}
}
- ./build/webpack.common.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
entry: {
main: './src/index.js',
},
output: {
path: path.resolve(__dirname, '../dist'),
filename: '[name].js'
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048
}
}
},{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
'postcss-loader'
]
},{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
'sass-loader',
'postcss-loader'
]
},{
test: /\.(eot|ttf|svg|woff)$/,
use: {
loader: 'file-loader',
}
}]
},
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html'
}),
new CleanWebpackPlugin()
],
optimization: {
splitChunks: {
chunks: 'all'
}
}
}
4-8 打包代码分析*****
- package.json
+"dev-build": "webpack --profile --json > stats.json --config ./build/webpack.dev.js"
- ./stats.json
webpack 生成
内容:对打包过程的描述
https://webpack.docschina.org/guides/code-splitting/#bundle-分析-bundle-analysis-
https://webpack.docschina.org/guides/code-splitting/#预取-预加载模块-prefetch-preload-module-
4-9
css 的代码分割
npm install --save mini-css-extract-plugin
- ./build/webpack.common.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
entry: {
main: './src/index.js',
},
output: {
path: path.resolve(__dirname, '../dist'),
filename: '[name].js',
+ chunkFilename: '[name].chunk.js'
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048
}
}
},
//- {
//- test: /\.css$/,
//- use: [
//- 'style-loader',
//- 'css-loader',
//- 'postcss-loader'
//- ]
//- },{
//- test: /\.scss$/,
//- use: [
//- 'style-loader',
//- {
//- loader: 'css-loader',
//- options: {
//- importLoaders: 2
//- }
//- },
//- 'sass-loader',
//- 'postcss-loader'
//- ]
//- },
{
test: /\.(eot|ttf|svg|woff)$/,
use: {
loader: 'file-loader',
}
}]
},
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html'
}),
new CleanWebpackPlugin()
],
optimization: {
+ usedExports: true
splitChunks: {
chunks: 'all'
}
}
}
- ./build/webpack.dev.js
const webpack = require('webpack')
const merge = require('webpack-merge')
const commonConfig = require('./webpack.common.js')
const devConfig = {
mode: 'development',
devtool: 'cheap-module-eval-source-map',
+ module: {
+ rules: [{
+ test: /\.css$/,
+ use: [
+ 'style-loader',
+ 'css-loader',
+ 'postcss-loader'
+ ]
+ },{
+ test: /\.scss$/,
+ use: [
+ 'style-loader',
+ {
+ loader: 'css-loader',
+ options: {
+ importLoaders: 2
+ }
+ },
+ 'sass-loader',
+ 'postcss-loader'
+ ]
+ }]
+ },
plugins: [
new webpack.HotModuleReplacementPlugin()
],
devServer: {
contentBase: './dist',
open: true,
port: 8080,
hot: true
},
- optimization: {
- usedExports: true
- }
}
module.exports = merge(commonConfig, devConfig)
- ./build/webpack.prod.js
const merge = require('webpack-merge')
const commonConfig = require('./webpack.common.js')
+const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const prodConfig = {
mode: 'production',
devtool: 'cheap-module-source-map',
+ plugins: [
+ new MiniCssExtractPlugin({
+ filename: "[name].css",
+ chunkFilename: "[id].css"
+ })
+ ],
+ module: {
+ rules: [{
+ test: /\.css$/,
+ use: [
+ MiniCssExtractPlugin.loader,
+ 'css-loader',
+ 'postcss-loader'
+ ]
+ },{
+ test: /\.scss$/,
+ use: [
+ MiniCssExtractPlugin.loader,
+ {
+ loader: 'css-loader',
+ options: {
+ importLoaders: 2
+ }
+ },
+ 'sass-loader',
+ 'postcss-loader'
+ ]
+ }]
+ }
}
module.exports = merge(commonConfig, prodConfig)
- package.json
{
"name": "lesson",
- "sideEffects": false,
+ "sideEffects": [
+ "*.css"
+ ],
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev-build": "webpack --config ./build/webpack.dev.js",
"dev": "webpack-dev-server --config ./build/webpack.dev.js",
"build": "webpack --config ./build/webpack.prod.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.7.7",
"@babel/plugin-syntax-dynamic-import": "^7.7.4",
"@babel/preset-env": "^7.7.7",
"@babel/preset-react": "^7.7.4",
"@types/node": "^12.12.21",
"autoprefixer": "^9.7.3",
"babel-loader": "^8.0.6",
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^3.4.0",
"express": "^4.17.1",
"file-loader": "^5.0.2",
"html-webpack-plugin": "^3.2.0",
"mini-css-extract-plugin": "^0.9.0",
"node-sass": "^4.13.0",
"postcss-loader": "^3.0.0",
"sass-loader": "^8.0.0",
"style-loader": "^1.0.2",
"url-loader": "^3.0.0",
"webpack": "^4.41.4",
"webpack-cli": "^3.3.10",
"webpack-dev-middleware": "^3.7.2",
"webpack-dev-server": "^3.10.1",
"webpack-merge": "^4.2.2"
},
"dependencies": {
"@babel/polyfill": "^7.7.0",
"lodash": "^4.17.15",
"react": "^16.12.0",
"react-dom": "^16.12.0"
}
}
合并
npm install --save-dev optimize-css-assets-webpack-plugin
- webpack.common.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin');
const { CleanWebpackPlugin } = require('clean-webpack-plugin')
module.exports = {
entry: {
main: './src/index.js',
},
output: {
path: path.resolve(__dirname, '../dist'),
filename: '[name].js',
chunkFilename: '[name].chunk.js'
},
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader'
},{
test: /\.(png|jpg|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
limit: 2048
}
}
},{
test: /\.(eot|ttf|svg|woff)$/,
use: {
loader: 'file-loader',
}
}]
},
plugins: [
new HtmlWebpackPlugin({
template: 'src/index.html'
}),
new CleanWebpackPlugin()
],
optimization: {
usedExports: true,
splitChunks: {
chunks: 'all'
}
}
}
- webpack.dev.js
const webpack = require('webpack')
const merge = require('webpack-merge')
const commonConfig = require('./webpack.common.js')
const devConfig = {
mode: 'development',
devtool: 'cheap-module-eval-source-map',
module: {
rules: [{
test: /\.css$/,
use: [
'style-loader',
'css-loader',
'postcss-loader'
]
},{
test: /\.scss$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
'sass-loader',
'postcss-loader'
]
}]
},
plugins: [
new webpack.HotModuleReplacementPlugin()
],
devServer: {
contentBase: './dist',
open: true,
port: 8080,
hot: true
}
}
module.exports = merge(commonConfig, devConfig)
- webpack.prod.js
const merge = require('webpack-merge')
const commonConfig = require('./webpack.common.js')
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin")
const prodConfig = {
mode: 'production',
devtool: 'cheap-module-source-map',
plugins: [
new MiniCssExtractPlugin({
filename: "[name].css",
chunkFilename: "[id].css"
})
],
module: {
rules: [{
test: /\.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader',
'postcss-loader'
]
},{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
importLoaders: 2
}
},
'sass-loader',
'postcss-loader'
]
}]
},
optimization: {
minimizer: [
new OptimizeCSSAssetsPlugin({})
]
}
}
module.exports = merge(commonConfig, prodConfig)
- package.json
{
"name": "lesson",
"sideEffects": [
"*.css"
],
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev-build": "webpack --config ./build/webpack.dev.js",
"dev": "webpack-dev-server --config ./build/webpack.dev.js",
"build": "webpack --config ./build/webpack.prod.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.7.7",
"@babel/plugin-syntax-dynamic-import": "^7.7.4",
"@babel/preset-env": "^7.7.7",
"@babel/preset-react": "^7.7.4",
"@types/node": "^12.12.21",
"autoprefixer": "^9.7.3",
"babel-loader": "^8.0.6",
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^3.4.0",
"express": "^4.17.1",
"file-loader": "^5.0.2",
"html-webpack-plugin": "^3.2.0",
"mini-css-extract-plugin": "^0.9.0",
"node-sass": "^4.13.0",
"optimize-css-assets-webpack-plugin": "^5.0.3",
"postcss-loader": "^3.0.0",
"sass-loader": "^8.0.0",
"style-loader": "^1.0.2",
"url-loader": "^3.0.0",
"webpack": "^4.41.4",
"webpack-cli": "^3.3.10",
"webpack-dev-middleware": "^3.7.2",
"webpack-dev-server": "^3.10.1",
"webpack-merge": "^4.2.2"
},
"dependencies": {
"@babel/polyfill": "^7.7.0",
"lodash": "^4.17.15",
"react": "^16.12.0",
"react-dom": "^16.12.0"
}
}