1、解决本地资源(css、js)打包报错问题【看dist文件夹下的css文件夹和js文件夹】
webpack在npm run dev
运行时会因为检测不到pulic文件夹下的css文件和js文件而报错。
npm install copy-webpack-plugin -D
修改webpack.config.js
文件的配置
const CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = {
plugins: [
//plugins数组放所有的webpack插件
new CopyWebpackPlugin([
{
from: "public/js/*.js",
to: path.resolve(__dirname, "dist", "js"),
//flatten属性只会拷贝文件,不会把文件路径也拷贝上
flatten: true
},
{
from:'public/css/*.css',
to:path.resolve(__dirname,'dist','css'),
flatten:true
}
],{
//忽略某个文件
ignore:['another.css','another.js']
})
],
}
其中如果把css的flatten设置为false,npm run dev
会出现如下报错:Refused to apply style from 'http://localhost:8000/css/base.css' because its MIME type ('text/html') is not a supported stylesheet MIME type, and strict MIME checking is enabled.
。npm run build
会生成这样一个dist文件夹:
如果把js的flatten设置为false,npm run dev
会出现如下报错:GET http://localhost:8000/js/base.js net::ERR_ABORTED 404 (Not Found)
。npm run build
会生成这样一个dist文件夹:
所以flatten
属性必须设置为true
2、抽离CSS【看dist文件夹下的css1文件夹】
安装mini-css-extract-plugin
npm install mini-css-extract-plugin -D
修改webpack.config.js
文件的配置
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
module: {
rules: [
{
test: /\.(le|c)ss$/,
use: [
//替换之前的style-loader
MiniCssExtractPlugin.loader,
// "style-loader",
"css-loader",
{
loader: "postcss-loader",
options: {
plugins: function() {
return [
//overrideBrowserslist被存储到.browserslistrc文件夹下
require("autoprefixer")()
];
}
}
},
"less-loader"
],
exclude: /node_modules/
}
]
},
plugins: [
//plugins数组放所有的webpack插件
new MiniCssExtractPlugin({
filename: "css1/[name].css",
// publicPath:'../'
})
],
}
这样在public文件夹下的css文件和js文件就被抽离出来了。css文件夹存放的是public文件夹下的css文件。css1文件夹存放的是src文件夹下的css文件。js文件夹存放的是public文件夹下的js文件
把css文件抽离出来之后,还要对css文件进行压缩
npm install optimize-css-assets-webpack-plugin -D
修改webpack.config.js
文件的配置
const OptimizeCssPlugin = require("optimize-css-assets-webpack-plugin");
module.exports = {
module: {
rules: [
{
test: /\.(le|c)ss$/,
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
hmr: isDev,
reloadAll: true
}
},
//替换之前的style-loader
// MiniCssExtractPlugin.loader,
// "style-loader",
"css-loader",
{
loader: "postcss-loader",
options: {
plugins: function() {
return [
//overrideBrowserslist被存储到.browserslistrc文件夹下
require("autoprefixer")()
];
}
}
},
"less-loader"
],
exclude: /node_modules/
},
]
},
plugins: [
//plugins数组放所有的webpack插件
new OptimizeCssPlugin()
],
}
npm run build
之后,css1文件下的main.css文件就被压缩了
body{
transition:all 2s}div{
background-color:red;color:green;font-size:20px;height:200px}
3、ProvidePlugin
ProvidePlugin不需要进行npm安装,因为它是webpack的内置插件。ProvidePlugind的作用就是无需进行import
或require
对库进行引入。
下面的代码示例引入了Vue、React、jQuery、map
module.exports = {
plugins: [
//plugins数组放所有的webpack插件
new webpack.ProvidePlugin({
//Vue的配置必须有default,因为vue.em.js是靠export default导出的
Vue: ["vue/dist/vue.esm.js", "default"],
//React不需要default,因为React是靠module.export导出的
React: "react",
Component: ["react", "Component"],
$: "jquery",
_map: ["lodash", "map"]
})
],
如果项目启动了 eslint
,还得在package-lock.json
文件的globals
添加react或vue等框架属性:
"globals": {
"version": "11.12.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
"dev": true,
"React":true,
"Vue":true
},
注:不建议过多使用ProvidePlugin,因为这样会减慢打包的速度、增加打包的负担。
4、webpack热更新
webpack热更新是指当我们修改了部分代码,但是我们不想看到页面全部重新加载的更新方法。
首先修改webpack.config.js
文件的配置
module.exports = {
devServer: {
//...
hot:true
},
plugins: [
new webpack.HotModuleReplacementPlugin()
]
}
修改入口文件
if (module && module.hot) {
module.hot.accept(['./js/base.js'], () => {
render()
})
}
这样的话js文件夹下的base.js文件发生改变时,整个页面不会全部重新加载。
5、多入口应用
首先先新建一个login.html文件(public文件夹)和一个login.js文件(src文件夹)。
然后修改webpack.config.js
文件的配置
module.exports = {
entry: {
index:'./src/index.js',
login:'./src/login.js'
},
plugins: [
new HtmlWebpackPlugin({
template: "./public/index.html",
filename: "index.html",
minify: {
removeAttributeQuotes: false,
collapseWhitespace: false
},
config: config.template
}),
new HtmlWebpackPlugin({
template: "./public/login.html",
filename: "login.html",
minify: {
removeAttributeQuotes: false,
collapseWhitespace: false
},
config: config.template
}),
]
}
npm run build
之后,index.html和login.html分别都引入了css1文件夹下的css文件和bundle.7dce74.js
(两次)。
因此还需要再次修改webpack.config.js
文件的配置。HtmlWebpackPlugin
插件提供了一个 chunks
的参数,该参数可以接受一个数组,配置该参数会将数组中指定的css文件引入到html文件中。
module.exports = {
entry: {
index:'./src/index.js',
login:'./src/login.js'
},
plugins: [
new HtmlWebpackPlugin({
template: "./public/index.html",
filename: "index.html",
minify: {
removeAttributeQuotes: false,
collapseWhitespace: false
},
config: config.template,
chunks:['login']
}),
new HtmlWebpackPlugin({
template: "./public/login.html",
filename: "login.html",
minify: {
removeAttributeQuotes: false,
collapseWhitespace: false
},
config: config.template,
chunks:['login']
}),
]
}
6、resolve 配置modules
webpack
内置 JavaScript
模块化语法解析功能,默认会采用模块化标准里约定好的规则去寻找,但我们可以根据自己的需要修改默认规则。
//webpack.config.js
module.exports = {
//....
resolve: {
modules: ['./src/components', 'node_modules']
}
}
这样配置以后,当我们 import FoodList from 'FoodList'
时,首先会去寻找 ./src/components
是否有FoodList组件;如果在 ./src/components
下找不到的话,就会到 node_modules
下寻找。
7、区别公共、开发、生产环境
之前的学习提到过,需要区分开发环境还是生产环境,我们可以根据 process.env.NODE_ENV
进行区分配置。
其实我们可以创建多个配置文件,如: webpack.base.js、webpack.dev.js、webpack.prod.js
- webpack.base.js:定义公共的配置。
- webpack.dev.js:定义开发环境的配置。
- webpack.prod.js:定义生产环境的配置。
8、定义环境变量
我们在开发环境中会使用本地域名,生产环境中使用线上域名,我们可以在 webpack 定义环境变量,方便在代码运行中知道是开发环境还是生产环境。使用 webpack 内置插件 DefinePlugin
来定义环境变量。
module.exports = {
plugins: [
new webpack.DefinePlugin({
DEV: JSON.stringify("dev"),
FLAG: "true"
})
]
}
在index.js入口文件中写到:
if (DEV === "dev") {
console.log("开发环境");
} else {
console.log("生产环境");
}
当我们运行npm run dev
时,会打印出“开发环境”
9、webpack跨域
新建一个server.js文件
let express = require("express");
let app = express();
app.get("/user", (req, res) => {
res.json({
name: "范梦羽" });
});
app.listen(4000);
修改index.js文件
fetch("/api/user")
.then(response => response.json())
.then(data => console.log(data))
.catch(err => console.log(err));
然后修改webpack.config.js
文件的配置
module.exports = {
devServer: {
proxy: {
"/api": {
target: "http://localhost:4000",
pathRewrite: {
//在配置代理时,去掉/api
api: ""
}
}
}
},
}
最后在Network中可以看到打印出来的数据
10、前端模拟数据
- (1)简单模拟数据
修改webpack.config.js
文件的配置
module.exports = {
devServer: {
before(app) {
app.get("/sex", (req, res) => {
res.json({
sex: "girl" });
});
}
},
}
修改index.js文件
fetch("sex")
.then(response => response.json())
.then(data => console.log(data))
.catch(err => console.log(err));
- (2)moke数据
先安装mocker-api
npm install mocker-api -D
修改webpack.config.js
文件的配置
const apiMocker = require("mocker-api");
module.exports = {
devServer: {
before(app) {
apiMocker(app, path.resolve("./mock/mocker.js"));
}
},
}
新建moke.js
module.exports = {
"GET /age": {
age: 21 },
"POST /login/account": (req, res) => {
const {
password, username } = req.body;
if (password === "888888" && username === "admin") {
return res.send({
status: "ok",
code: 0,
token: "sdfsdfsdfdsf",
data: {
id: 1, age: 21 }
});
} else {
return res.send({
status: "error", code: 403 });
}
}
};
修改index.js
fetch("/login/account", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
username: "admin",
password: "888888"
})
})
.then(response => response.json())
.then(data => console.log(data))
.catch(err => console.log(err));
详情可查看我搭建的webpackTest