1、
做项目的时候看到package.json里script标签里分了好多不同的环境,比如
start:dev;start:test;start:prod;对应的就是开发、测试、生产环境。这样分不同环境的目的就是当你启动和打包项目的时候可以启用或者打包对应环境的服务和包。
那么问题来了,当执行不同命令时候是怎么做到这一点的?
2、正好前段时间做了个h5项目,前端同事给了我个他搭建的基于Taro的架子,现在就拿这个架子为例
可以看到package.json里分了四个环境,启动项目的时候执行的命令是对应环境的build命令,在这个基础上加了--watch(是webpack的参数吗?) ;而在build命令里面多了很多东西,如cross-env MODE_ENV=app-mero CONF_ENV=dev taro build --type h5。问题1):这些参数干嘛用的?问题2):这些参数怎么用? 猜测:这些参数就是用于区分环境的,尤其是CONF_ENV,可以看到不同环境这个变量值不一样。
3、带着这些问题看下项目config/index.js的内容
const path = require('path')
const webpack = require('webpack')
const config = {
projectName: 'taro-h5',
date: '2023-3-20',
designWidth: 750,
deviceRatio: {
640: 2.34 / 2,
750: 1,
828: 1.81 / 2
},
sourceRoot: 'src',
outputRoot: 'dist',
plugins: [
// "taro-plugin-compiler-optimization",
["@tarojs/plugin-html", {
// 包含 `van-` 的类名选择器中的 px 单位不会被解析
// pxtransformBlackList: [/van-/]
}],
// new webpack.DefinePlugin({ // webpack自带该插件,无需单独安装
// 'process.env' : {
// NODE_ENV: process.env.NODE_ENV // 将属性转化为全局变量,让代码中可以正常访问
// }
// })
],
alias: {
'@': path.resolve(__dirname, '..', 'src'),
'@images': path.resolve(__dirname, '..', 'src/assets/images'),
//'regenerator-runtime': path.resolve(__dirname, '../node_modules', 'regenerator-runtime'),
},
defineConstants: {
},
copy: {
patterns: [
],
options: {
}
},
framework: 'react',
compiler: 'webpack5',
terser: {
enable: true, // 是否开启代码压缩
config: {
// 配置项同 https://github.com/terser/terser#minify-options
}
},
cache: {
enable: false // Webpack 持久化缓存配置,建议开启。默认配置请参考:https://docs.taro.zone/docs/config-detail#cache
},
mini: {
enableExtract:true,
optimizeMainPackage: {
enable: true
},
miniCssExtractPluginOption: {
//忽略css文件引入顺序
ignoreOrder: true
},
esnextModules: ['@antmjs', "taro-ui"],
webpackChain(chain, webpack) {
if(process.env.NODE_ENV !== 'development'){//只在生产环境下生效
chain.mode("production");
chain.merge({
performance: {
hints: "warning", // 枚举
maxAssetSize: 10000000, // 整数类型(以字节为单位)
maxEntrypointSize: 10000000, // 整数类型(以字节为单位)
},
/* plugin: {
terse: {
plugin: TerserPlugin,
args: [
{
minify: TerserPlugin.swcMinify,
terserOptions: {
compress: {
pure_funcs: process.env.CONF_ENV === "prod" ? ["console.log"] : [] //过滤掉打印
}
},
}
]
}
}, */
})
}
},
postcss: {
pxtransform: {
enable: true,
config: {
}
},
url: {
enable: true,
config: {
limit: 1024 // 设定转换尺寸上限
}
},
cssModules: {
enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
config: {
namingPattern: 'module', // 转换模式,取值为 global/module
generateScopedName: '[name]__[local]___[hash:base64:5]'
}
}
}
},
h5: {
publicPath: '/',
staticDirectory: 'static',
esnextModules: ['@antmjs', "taro-ui"],
router: {
mode: 'browser' // 或者是 'hash'
},
output: {
filename: 'js/[name].[hash:8].js',
chunkFilename: 'chunk/[name].[chunkhash:8].js'
},
miniCssExtractPluginOption: {
filename: 'css/[name].[hash:8].css',
chunkFilename: 'css/[name].[chunkhash:8].css',
},
imageUrlLoaderOption: {
limit: 1024,
name: 'static/images/[name].[hash:8].[ext]'
},
postcss: {
autoprefixer: {
enable: true,
config: {
}
},
cssModules: {
enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
config: {
namingPattern: 'module', // 转换模式,取值为 global/module
generateScopedName: '[name]__[local]___[hash:base64:5]'
}
}
},
devServer: {
// port: 10086,
// hot: true,
// historyApiFallback: true,
// disableHostCheck: true,
host:'',
port:8086,
proxy:{
/*******************猛士门户********************** */
'/api': {
target: 'https://mhero.dfmc.com.cn',
// target: 'https://admin-recharge-uat.geely-test.com/api/',
changeOrigin: true,
pathRewrite: { '^/api': '' },
// secure: false,
},
'/m-interface-api': {
// target: 'http://10.81.64.16:2046',
// target:'https://mhero.dfmc.com.cn',
target:'http://10.81.64.49:8087',
changeOrigin: true,
pathRewrite: { '^/m-interface-api': 'm-interface-api' },
// secure: false,
},
},
// headers: {
// 'Access-Control-Allow-Origin': '*', // 表示允许跨域
// },
},
},
rn: {
appName: 'taroDemo',
postcss: {
cssModules: {
enable: false, // 默认为 false,如需使用 css modules 功能,则设为 true
}
}
}
}
module.exports = function (merge) {
if (process.env.NODE_ENV === 'development') {
if(process.env.MODE_ENV === 'app-mero') {
return merge({}, config, require(`./mhero/${process.env.CONF_ENV}`))
}
return merge({}, config, require(`./weapp/${process.env.CONF_ENV}`))
}
return ((mode)=> {
if(mode && mode === 'app-mero') {
return merge({}, config, require(`./mhero/${process.env.CONF_ENV}`))
}
return merge({}, config, require(`./weapp/${process.env.CONF_ENV}`))
})(process.env.MODE_ENV)
}
看这段代码
module.exports = function (merge) {
if (process.env.NODE_ENV === 'development') {
if(process.env.MODE_ENV === 'app-mero') {
return merge({}, config, require(`./mhero/${process.env.CONF_ENV}`))
}
}
return ((mode)=> {
if(mode && mode === 'app-mero') {
return merge({}, config, require(`./mhero/${process.env.CONF_ENV}`))
}
})(process.env.MODE_ENV)
}
可以看到根据CONF_ENV变量的不同加载不同的配置文件,配置文件列表如下:
dev.js 文件内容如下:
const path = require("path");
const webpack = require("webpack");
module.exports = {
env: {
NODE_ENV:
process.env.NODE_ENV === "development" ? '"development"' : '"production"', // '"development"'
CONF_ENV: '"dev"',
MODE_ENV: '"app-mero"',
},
defineConstants: {
SUB_MODE: '"app-mero"',
},
Plugin: [
// path.resolve(__dirname, 'config/plugins/minifyMainPackage.js'),
],
mini: {},
outputRoot: "dist/h5",
h5: {
publicPath: "/h5/",
router: {
basename: "/h5",
mode: "browser", // 或者是 'hash'
},
},
};
现在看这个方法里面的东西:module.exports = function (merge){}
问题 这种写法是谁支持的?webpack?Taro?process.env.NODE_ENV又是啥东西,有啥用?
继续探索
Taro官网给出的配置方式:
实现了根据NODE_ENV不同而加载不同配置文件,下一个问题NODE_ENV、MODE_ENV、CONF_ENV 这些变量哪里来的,什么时候生成的?
process.env
是 Node.js
中的一个环境对象,NODE_ENV
就是其中的一个环境变量,该变量可以通过node配置,也可以在项目中配置。Taro里启用服务默认是development,打包默认是production,
这个NODE_ENV也可以改,在哪里改呢?一个是通过命令里改,另外一个通过webpack配置文件改
如下:
命令
webpack配置(如果是development则为development,否则就是production。据说是production的时候package.json的依赖有部分下载不了,所以做如此区分)
经验证:MODE_ENV、CONF_ENV都是在运行打包命令时变量的值已经赋值,通过process.env.
MODE_ENV process.env.
CONF_ENV来获取
4、cross-env是干嘛的
cross-env:运行跨平台设置和使用环境变量的脚本。简单来讲就是为了跨平台设置环境变量的,比如没有它,你在Windows设置NODE_ENV=development会阻塞,有了它你设置NODE_ENV=development就不会报错
关于webpack配置、打包这些才开始学习,写的比较菜,随手笔记供自己记录,后续有新的认识会更新。
每天进步一点,别人可以你也可以