Webpack 学院 #6:拆分开发和生产模式的配置
所以从现在开始我们可以管理很多事情,但我们需要将配置分为两部分:
-
开发部分(针对开发人员)
-
生产部分(当我们在网络上部署应用程序时)
到目前为止我们只关注产品部分!
因此在本文中,我们将把配置分成 3 个文件!
-
webpack 常用配置
-
产品配置
-
开发配置
webpack 常用配置
一些属性对于 dev 和 prod 配置文件来说是通用的,因此我们可以创建一个包含这些字段的文件以避免重复代码!
开始之前,我们需要安装一个名为 的包webpack-merge
,它会将两个配置文件合并为一个!这样我们就可以将 .merge-common 文件与 .merge-common 文件合并了!
此后,我们创建一个通用配置文件👇
const { CleanWebpackPlugin } = require("clean-webpack-plugin")
const HtmlWebpackPlugin = require('html-webpack-plugin')
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
const cdn = require("./cdn")
const config = {
// Webpack start from this entry point
entry: {
myApp: [
"./src/style.css",
"./src/main.js",
],
},
// External lib that will not be put in bundle but use from CDN
externals: {
lodash: '_',
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: 'Webpack academy title',
template: './src/index.html',
inject: 'body',
cdn,
minify: {
removeComments: true,
collapseWhitespace: false
}
}),
new BundleAnalyzerPlugin({
openAnalyzer: true,
analyzerMode: 'server',
})
],
}
module.exports = config
在通用配置中,我们需要使用捆绑分析器进行生产和开发模式,我们还需要HTML 插件和干净的 webpack!
我们还需要使用cdn!
我们创建了一个产品配置文件!
产品配置文件
const commonConfig = require("./webpack.config.common")
const merge = require('webpack-merge')
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
const config = {
mode: "production",
module: {
rules: [
{
// Match file extension
test: /\.css$/,
// Order of loader from bottom to up
use: [
MiniCssExtractPlugin.loader,
'css-loader'
],
}
]
},
// This is the output of Webpack
output: {
// From current folder + dist folder that will contains all bundle
path: path.resolve(__dirname, "dist/"),
filename: "[contenthash:8].js"
},
optimization: {
minimize: true,
},
plugins: [
new MiniCssExtractPlugin({
// Name output by extract
filename: "style.css",
}),
],
}
// Merge commonConfig with prod config, priority to prod config
module.exports = merge(commonConfig, {
...config,
})
在生产模式下,我们需要使用哈希、提取 css并最小化捆绑代码!
生产部分几乎完成了,我们需要重命名cdn
文件,cdn.prod.js
因为我们将在生产和开发模式下为 cdn 使用两个单独的文件!
我们需要编辑script file
👇
"build": "cross-env --env.NODE_ENV=prod webpack --config webpack.config.prod.js"
从现在起,生产部分已经完成!
一切进展顺利!这是一个很好的开始,让我们继续推进生产部分!
开发配置文件
让我们开始创造吧cdn.dev
!
不同的是prod cdn
,我们不会使用minify
库的版本!我们只会使用经典版本!
module.exports = {
js: [
"https://unpkg.com/lodash@4.17.15/lodash.js",
],
}
在此之后,我们需要安装webpack-dev-server
,它用于像开发人员的开发服务器一样处理开发服务!
并创建开发配置👇
const path = require("path")
const commonConfig = require("./webpack.config.common")
const merge = require('webpack-merge')
const config = {
mode: "development",
devServer: {
// Show info about dev server
noInfo: false,
// Port of dev server
port: 8080,
// Asking the server to fallback to index.html in the event that a requested resource cannot be found, need to vue router
historyApiFallback: true,
// Allows https in dev server
// Use this https://stackoverflow.com/questions/35531347/localhost-blocked-on-chrome-with-privacy-error for allow https in localhost directly on chrome
https: true,
},
// This is the output of Webpack
output: {
// From current folder + dist folder that will contains all bundle
path: path.resolve(__dirname, "dist/"),
filename: "bundle.dev.js"
},
module: {
rules: [
{
// Match file extension
test: /\.css$/,
// Use multiple loader
// Order => from bottom to top
use: [
'style-loader',
'css-loader'
],
}
]
}
}
// Merge commonConfig with prod config, priority to prod config
module.exports = merge(commonConfig, {
...config,
})
因为css part
我们需要使用,style-loader
因为我们需要在 DOM 中注入样式!
我们使用一些属性,例如port
,https
等等......(查看上面的评论)
但有一件事非常有趣,我应该向你解释一下🔥
historyApiFallback:
当您使用 Vuejs 或 React 之类的框架时,您将在两件事之间进行选择 -> 在前端或后端使用路由器。
例如,如果您使用 vuejs,则需要使用VueRouter(在前端处理应用程序的路由)。
您需要通知托管您的应用程序的当前服务器(在我的情况下是 webpack 服务器),您通过前端处理路由而不是通过服务器(后端)处理路由。
但为什么 ?
例如,如果您使用路由器前端,您将尝试此 URL 👇
https://toto.com/test
服务器将尝试从服务器文件中访问/test
文件,但由于该文件不存在(因为你通过前端处理路由),因此不会得到任何结果。你将得到一个404
!
为了避免这种情况,我们需要告诉服务器 ->If you have a 404, access to the root file (main file) and not looking for /test file
此后,您可以输入任何 URL,您的项目就会运行!
因此,此选项historyApiFallback
只是为了防止这种情况发生,如果您在前面部分使用路由器,则应该放true
!否则放false
!
我们快完成了💪
创建命令以在开发模式下运行我们的应用程序
"dev": "cross-env --env.NODE_ENV=dev webpack serve --hot --config webpack.config.dev.js",
webpack serve --hot
:以热重载模式运行 webpack 服务器的命令(当文件发生更改时,我们会自动重新加载项目)
源图
我们不会详细介绍这一点,如果你想查看这个网址 -> https://blog.teamtreehouse.com/introduction-source-maps
简而言之,在开发模式下,我们需要调试一些文件,如果我们不使用源映射,我们将会有一些有点奇怪的文件,例如我们的main.js
👇
lodash__WEBPACK_IMPORTED_MODULE_1___default().cloneDeep({})
console.log(_three__WEBPACK_IMPORTED_MODULE_0__.three)
document.getElementById("button").addEventListener("click", function() {
jsonObjectImport().then(jsonObject => console.log(jsonObject.default))
})
在这里这不是问题,但是对于大文件,我们在调试时可能会遇到一些麻烦!
我们的英雄也是source map
!🦸♂️
devtool: 'eval-cheap-source-map',
(关于源映射,您有很多选择,对我来说,在开发中最好使用“eval-cheap-source-map”),请查看此 URL 以获取更多信息:https://webpack.js.org/configuration/devtool/
当你想要调试时main.js
,你会看到另一个文件,就像main.js?56d7
这样,这就是我们需要调试的文件!打开它,👇
import { three } from './three'
import _ from 'lodash'
const jsonObjectImport = async () => import(/* webpackChunkName: "myChunkName" */ "./big-object.json")
_.cloneDeep({})
console.log(three)
document.getElementById("button").addEventListener("click", function() {
jsonObjectImport().then(jsonObject => console.log(jsonObject.default))
})
这就像我们的原始main.js
文件一样!
总结一下源图:
当我们使用 Webpack 捆绑我们的代码时,它会将我们的原始文件编译成另一个特殊文件(可能很奇怪),所以如果我们想要调试我们的代码,我们将拥有这个与原始文件代码不同的特殊文件。
为了解决这个问题,我们可以使用源映射来跟踪原始文件(每个原始文件都有一个特殊的哈希值)。这样,如果我们需要调试代码,就可以像找到原始文件一样找到该文件!
做得好!💪🔥
我们成功了!我们成功将原始配置拆分成两部分!
我们即将完成 webpack 学院的课程!
我希望你喜欢这个,你可以在这个提交中查看源代码
📝 注意:如果我们需要在两种情况下检查包大小,我们会在 prod 和 dev 模式下为包分析器创建另外两个命令
我希望你喜欢这篇文章!
🎁 如果您在TwitterUnderrated skills in javascript, make the difference
上关注我并给我点赞,即可免费获得我的新书😁
或者在这里获取
☕️ 你可以支持我的作品🙏
🏃♂️ 你可以关注我 👇
🕊 推特:https://twitter.com/code__oz
👨💻 Github:https://github.com/Code-Oz
你也可以标记🔖这篇文章!
鏂囩珷鏉ユ簮锛�https://dev.to/codeoz/webpack-academy-6-split-your-config-for-dev-prod-mode-2le7