"dev": "webpack-dev-server --mode development",
"webpack-dev-server": "^3.2.1"
"scripts": {
"dev": "webpack-dev-server --mode development",
"build": "webpack --mode production",
},
"devDependencies": {
"webpack": "^4.29.6",
"webpack-cli": "^3.2.3",
"webpack-dev-server": "^3.2.1"
}
module.exports = {
// webpack执行打包的唯一入口
entry: {
main: [path.resolve(__dirname, './src/main.js')],
},
// 打包的输入
output: {
publicPath: '', //
// 将所有依赖的模块合并输出到main_xxxxxx.js,xxxxxx为随机生成的6位hash码
//当内容有改变时,hash会变化,防止缓存原因导致修改不更新
filename: 'js/[name]_[contenthash:6].js',
// 输出文件的存放路径, 必须是绝对路径
path: path.resolve(__dirname, "./dist")
},
// 本地开发环境配置
devServer: {
contentBase: path.resolve(__dirname, "./dist"), //指定被访问html页面所在的目录的
open: true, // 指运行npm run server指令后,自动在浏览器里打开一个页面
port: 8081, // 指定打开的页面的端口为8081,也可以指定其他端口
inline: true, // 页面实时刷新
// host:"127.0.0.1" // 地址 http://127.0.0.1:8081/
overlay: true, // 如果代码出错,会在浏览器页面弹出“浮动层”。类似于 vue-cli 等脚手架
proxy: {
// 跨域代理转发
'/api': {
target: 'http://102.03.34.58',
pathRewrite: {
'^/api': ''
}
}
},
historyApiFallback: {
// HTML5 history模式
rewrites: [{
from: /.*/,
to: '/index.html'
}]
}
},
}
// 全局引入
// import '@babel/polyfill'
console.log("main");
import {
age
} from "./person"
console.log("age", age);
let a = 10;
console.log("a", a);
const set = new Set([1, 2, 3, 1])
console.log('res,', set, '; set-arr', [...set]) // res, Set(3) {1, 2, 3} ; set-arr (3) [1, 2, 3]
import "./css/main.css"
import "./css/index.scss"
import {
add
} from "./utils/index"
console.log("add", add(2, 2)); // add 4
import _ from "lodash"
console.log("使用lodash", _.add(22, 33)); // 使用lodash 55
import Vue from "vue"
import App from "./App.vue";
const app = new Vue({
el:'#app',
render: (h) => h(App), //h就是vue中的createApp参数
})
<template>
<div id="app">
<div class="bg">msg - {{ msg }}</div>
<div class="box">我是box-11-1</div>
</div>
</template>
<script>
export default {
data() {
return {
msg: 'msg-msg-1'
}
}
}
</script>
<style scoped>
#app {
font-size: 40px;
}
.bg {
background: yellow;
}
.box{
width: 100px;
height: 100px;
background: pink;
font-size: 20px;
}
</style>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
</div>
</body>
</html>
于终端起一个服务,点击链接,可加载出开发时的代码效果
页面效果
"scripts": {
"dev": "webpack-dev-server --config ./build/webpack.config.dev.js",
"build": "webpack --config ./build/webpack.config.prod.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"devDependencies": {
"webpack-merge": "^4.2.1"
},
const path = require("path");
const MiniCssExtractPlugin = require('mini-css-extract-plugin') // 将 css 单独打包成文件
const HtmlWebpackPlugin = require('html-webpack-plugin') // 自动引入文件 插件
const {
CleanWebpackPlugin
} = require('clean-webpack-plugin') // 版本为2.0.0 不需要 { CleanWebpackPlugin } 结构! 大于2.0.0则需要
module.exports = {
// webpack执行打包的唯一入口
entry: {
// main: [path.resolve(__dirname, './src/main.js')],
main: "./src/main.js"
},
// 打包的输入
output: {
publicPath: '', //
// 将所有依赖的模块合并输出到main_xxxxxx.js,xxxxxx为随机生成的6位hash码
//当内容有改变时,hash会变化,防止缓存原因导致修改不更新
filename: 'js/[name]_[contenthash:6].js',
// 输出文件的存放路径, 必须是绝对路径
path: path.resolve(__dirname, "../dist") // path.resolve(__dirname, "./dist")
},
// loader相关配置
module: {
rules: [{
test: /\.(sa|sc|c)ss$/, // 针对 .sass .scss 或者 .css 后缀的文件设置 loader
use: [{
loader: "vue-style-loader"
},
// MiniCssExtractPlugin.loader,
{
loader: MiniCssExtractPlugin.loader
},
'css-loader',
'postcss-loader', // 使用 postcss 为 css 加上浏览器前缀
'sass-loader' // 使用 sass-loader 将 scss 转为 css
]
},
{
test: /\.js$/, // 使用正则来匹配 js 文件
exclude: /node_modules/, // 排除依赖包文件夹
use: {
loader: 'babel-loader' // 使用 babel-loader
}
},
{
test: /\.(png|jpg|jpeg|gif|webp)$/,
use: [{
loader: 'url-loader',
options: {
name: '[name]-[hash:5].min.[ext]',
outputPath: 'images/', //输出到 images 文件夹
limit: 20000 //把小于 20kb 的文件转成 Base64 的格式
}
},
// 使用 image-webpack-loader 对图片进行压缩
{
loader: "image-webpack-loader",
options: {
mozjpeg: {
progressive: true,
quality: 65
},
optipng: {
enabled: false
},
pngquant: {
quality: '65-90',
speed: 4
},
gifsicle: {
interlaced: false
},
webp: {
quality: 75
}
}
},
]
},
{
test: /\.vue$/,
loader: 'vue-loader'
},
]
},
resolve: {
extensions: ['.js', '.css', '.scss', '.vue', '.json'], // 引入的时候 可以省略后缀
alias: {
'vue$': 'vue/dist/vue.esm.js'
}
},
plugins: [
//默认情况下,此插件删除 webpack output.path目录中的所有文件,以及每次成功重建后所有未使用的 webpack 资产
new CleanWebpackPlugin(),
// 自动生成html ( 于打包后 dist目录下的 双击在浏览器显示 )
new HtmlWebpackPlugin({
// 打包输出HTML
title: '自动生成 HTML',
minify: {
// 压缩 HTML 文件
removeComments: true, // 移除 HTML 中的注释
collapseWhitespace: true, // 删除空白符与换行符
minifyCSS: true // 压缩内联 css
},
filename: 'index.html', // 生成后的文件名
template: 'index.html', // 根据此模版生成 HTML 文件
// chunks: ['main'] // entry中的 app 入口才会被打包
}),
// 分割css
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css'
}),
]
}
const path = require("path");
const merge = require("webpack-merge")
const baseConfig = require("./webpack.config.base")
const devConfig = {
output: {
filename: '[name].js',
chunkFilename: '[name].js'
},
mode: 'development',
devtool: 'source-map', // 调试源码
// 本地开发环境配置
devServer: {
contentBase: path.resolve(__dirname, "../dist"), //指定被访问html页面所在的目录的
open: true, // 指运行npm run server指令后,自动在浏览器里打开一个页面
port: 8081, // 指定打开的页面的端口为8081,也可以指定其他端口
inline: true, // 页面实时刷新
// host:"127.0.0.1" // 地址 http://127.0.0.1:8081/
overlay: true, // 如果代码出错,会在浏览器页面弹出“浮动层”。类似于 vue-cli 等脚手架
proxy: {
// 跨域代理转发
'/api': {
target: 'http://102.03.34.58',
pathRewrite: {
'^/api': ''
}
}
},
// historyApiFallback: true
historyApiFallback: {
// HTML5 history模式
rewrites: [{
from: /.*/,
to: '/index.html'
}]
}
},
// module: {
// rules: [{
// test: /\.(sa|sc|c)ss$/, // 针对 .sass .scss 或者 .css 后缀的文件设置 loader
// use: [
// 'style-loader',
// {
// loader: "vue-style-loader"
// },
// {
// loader: MiniCssExtractPlugin.loader
// },
// 'css-loader',
// 'postcss-loader', // 使用 postcss 为 css 加上浏览器前缀
// 'sass-loader' // 使用 sass-loader 将 scss 转为 css
// ]
// }]
// }
}
module.exports = merge(baseConfig, devConfig)
const path = require("path");
const MiniCssExtractPlugin = require('mini-css-extract-plugin') // 将 css 单独打包成文件
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin') // 压缩 css
const HtmlWebpackPlugin = require('html-webpack-plugin') // 自动引入文件 插件
const {
CleanWebpackPlugin
} = require('clean-webpack-plugin') // 版本为2.0.0 不需要 { CleanWebpackPlugin } 结构! 大于2.0.0则需要
// 去掉 不加载的css
const PurifyCSS = require('purifycss-webpack')
const glob = require('glob-all')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); //压缩js
const merge = require("webpack-merge")
const baseConfig = require("./webpack.config.base")
const prodConfig = {
mode: 'production',
// 代码切片相关
optimization: {
// 代码切片 分割 打包后分割为多个 .js文件
splitChunks: {
chunks: 'all',
// 打包后的效果
// js/lodash_950848.js 71.1 KiB 0 [emitted] lodash
// js/main_63de8b.js 1.78 KiB 1 [emitted] main
// js/vendors~main_2938f3.js 112 KiB 2 [emitted] vendors~main
cacheGroups: {
lodash: {
name: 'lodash',
test: /[\\/]node_modules[\\/]lodash[\\/]/,
priority: 5 // 优先级要大于 vendors 不然会被打包进 vendors
},
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10 // 打包node_modules
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
},
},
plugins: [
//默认情况下,此插件删除 webpack output.path目录中的所有文件,以及每次成功重建后所有未使用的 webpack 资产
new CleanWebpackPlugin(),
// 清除无用 css
new PurifyCSS({
paths: glob.sync([
// 要做 CSS Tree Shaking 的路径文件
path.resolve(__dirname, './*.html'), // 请注意,我们同样需要对 html 文件进行 tree shaking
path.resolve(__dirname, './src/*.js')
])
}),
// // 分割css
// new MiniCssExtractPlugin({
// filename: '[name].css',
// chunkFilename: '[id].css'
// }),
// 压缩css
new OptimizeCssAssetsPlugin({
assetNameRegExp: /\.optimize\.css$/g,
cssProcessor: require('cssnano'),
cssProcessorPluginOptions: {
preset: ['default', {
discardComments: {
removeAll: true
}
}],
},
canPrint: true
}),
// 压缩js
new UglifyJsPlugin(),
]
}
module.exports = merge(baseConfig, prodConfig)
<template>
<div id="app">
<div class="bg">msg - {{ msg }}</div>
<div class="box">我是box-11-1-111-1</div>
</div>
</template>
<script>
export default {
data() {
return {
msg: 'msg-msg-1'
}
}
}
</script>
<style scoped>
#app {
font-size: 40px;
}
.bg {
background: yellow;
}
.box{
width: 100px;
height: 100px;
background: pink;
font-size: 20px;
}
</style>
// 全局引入
// import '@babel/polyfill'
console.log("main");
import {
age
} from "./person"
console.log("age", age);
let a = 10;
console.log("a", a);
const set = new Set([1, 2, 3, 1])
console.log('res,', set, '; set-arr', [...set]) // res, Set(3) {1, 2, 3} ; set-arr (3) [1, 2, 3]
import "./css/main.css"
import "./css/index.scss"
import {
add
} from "./utils/index"
console.log("add", add(2, 2)); // add 4
import _ from "lodash"
console.log("使用lodash", _.add(22, 33)); // 使用lodash 55
import Vue from "vue"
import App from "./App.vue";
const app = new Vue({
el:'#app',
render: (h) => h(App), //h就是vue中的createApp参数
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
</div>
</body>
</html>
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"corejs": 3
}
]
],
"plugins": ["@babel/plugin-transform-runtime"]
}
module.exports = {
plugins: [
require('autoprefixer')
// , require('postcss-pxtorem')({
// remUnit: 50, // 50px = 1rem
// remPrecision: 2 // rem的小数点后位数
// })
]
}
mian.css
body {
/* background: yellow; */
/* 29kb 效果 background: url(images/dog1-afa6a.min.webp); */
background: url("../img/dog.webp");
/* 4.4kb 效果 background: url(data:image/webp;base64,UklGRpYRA。。。。 */
/* background: url("../img/hlw.webp") */
/* 注意点:配置了图片的大小压缩 小于20kb 转化为base64 */
}
index.scss
$bgColor: red !default;
html {
p {
background-color: $bgColor;
}
.ppp {
display: flex;
justify-content: flex-end;
color: #fff;
font-size: 16px;
border: 2px solid #ccc;
}
.box {
width: 100px;
height: 100px;
border: 2px solid red;
}
}