前言:文件依赖关系错综复杂,静态资源请求效率低,模块化支持不友好,浏览器对高级JS兼容程度低?那就是时候了解webpack了
webpack 是一个JavaScript 应用程序的静态模块打包构建器。在处理应用程序时, webpack 会递归地构建一个依赖关系图,其中包含应用程序需要的每个模块,然后将所有这些模块打包成一个或多个 bundle。webpack提供了友好的模块化支持,以及代码压缩混淆、高级js兼容、性能优化。
入口起点(entry point)指示 webpack 使用哪个模块,作为构建其内部依赖图的开始。进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。
webpack.config.js:
module.exports = {
entry: {
main: './src' //打包入口,来指定一个入口起点(或多个入口起点,默认值为 ./src)
},
entry: './src', //这个是上面的简写方式,是等价的
entry: {
home: "./home.js",
about: "./about.js",
contact: "./contact.js"
},//对象法指定多个入口,如果你想要多个依赖一起注入到一个模块,向 entry 属性传入「文件路径(file path)数组」。
entry: () => new Promise((resolve) => resolve(['./demo', './demo2'])),//动态入口,当结合 output.library 选项时:如果传入数组,则只导出最后一项
};
output 属性告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件。基本上,整个应用程序结构,都会被编译到你指定的输出路径的文件夹中。
webpack.config.js:
const path = require('path');
module.exports = {
output: {
path: path.resolve(__dirname, 'dist'),//打包文件夹名,默认值为 ./dist
filename: '[name].js'//入口文件名
}
};
loader 用于转换某些类型的模块,webpack 自身只理解 JavaScript,loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块。loader 能够 import 导入任何类型的模块(如 .css),是 webpack 特有的功能,其他打包工具有可能不支持。
webpack.config.js:
const path = require('path');
const config = {
module: {
rules: [//在 webpack 配置中定义 loader 时,要定义在 module.rules 中,里面包含两个"必须属性":test 和 use
{
test: /\.txt$/, //test 定义需要使用相应 loader 进行转换的某类文件
use: 'raw-loader' //use 定义使用哪个 loader 进行转换
}
]
}
};
module.exports = config;
插件接口功能极其强大,可以用来处理各种各样的任务。通过require() 使用插件,然后把它添加到 plugins 数组中。多数插件可以通过选项(option)自定义。
webpack.config.js:
const htmlWebpackPlugin = require('html-webpack-plugin'); // 通过 npm 安装
const webpack = require('webpack'); // 用于访问内置插件
const config = {
plugins: [
//在一个配置文件中因为不同目的而多次使用同一个插件,需要通过使用 new 操作符来创建它的一个实例
new webpack.optimize.UglifyJsPlugin(),
new HtmlWebpackPlugin({template: './src/index.html'})
]
};
module.exports = config;
module.exports = {
mode: 'production'//通过选择 development(开发) 或 production(生产),启用相应模式下的 webpack 内置的优化
};
webpack 需要传入一个配置对象, 根据对象定义的属性进行解析,因此很少有 webpack 配置看起来很完全相同。 webpack 的配置文件,是导出一个对象的 JavaScript 文件。可以通过两种方式(终端、Node.js)使用 webpack。
webpack 配置是标准的 Node.js CommonJS 模块,你可以:
通过 require(...) 导入其他文件通过 require(...) 使用 npm 的工具函数使用 JavaScript 控制流表达式,例如 ?: 操作符对常用值使用常量或变量编写并执行函数来生成部分配置应避免以下做法:
在使用 webpack 命令行接口(CLI)(应该编写自己的命令行接口(CLI),或使用 --env)时,访问命令行接口(CLI)参数导出不确定的值(调用 webpack 两次应该产生同样的输出文件)编写很长的配置,应该将配置拆分为多个文件webpack 配置是标准的 Node.js CommonJS 模块,在安装webpack之前,请确保安装了 Node.js 的最新版本,使用旧版本可能遇到各种问题(可能缺少 webpack 功能或者缺少相关 package 包)。
对于大多数项目,建议本地安装。这可以在引入破坏式变更(breaking change)的依赖时,更容易分别升级项目。不推荐全局安装 webpack。这会将你项目中的 webpack 锁定到指定版本,并且在使用不同的 webpack 版本的项目中,可能会导致构建失败。
①本地安装
npm install --save-dev webpack //安装最新版本
npm install --save-dev webpack@<version> //安装特定版本
②全局安装
npm install --global webpack
如果你使用 webpack 4+ 版本,你还需要安装 CLI,此工具用于在命令行中运行 webpack。
npm install --save-dev webpack-cli //webpack-cli用于在命令行中运行 webpack
在已有的项目中:
npm init -y //初始化webpack 这里会自动生成一个package.json
npm i -D webpack webpack-cli //安装webpack及其脚手架
一个项目包两个项目demo1和demo2(适用于两个项目功能需求很类似有公用的地方有不同的地方):
{
"name": "webpackstudy",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"demo1-start": "webpack-dev-server --progress --color",
"demo2-start": "webpack-dev-server --progress --color",
"demo1-mock": "webpack-dev-server --progress --color",
"demo2-mock": "webpack-dev-server --progress --color",
"demo1-te": "webpack --progress --color",
"demo2-te": "webpack --progress --color"
},
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^0.19.0",
"vue": "^2.6.10",
"vue-pull-to": "^0.1.8",
"vue-router": "^3.1.2",
"vuex": "^3.1.1"
},
"devDependencies": {
"@babel/core": "^7.5.5",
"@babel/preset-env": "^7.5.5",
"autoprefixer": "^9.6.1",
"babel-loader": "^8.0.6",
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^3.2.0",
"file-loader": "^4.2.0",
"html-webpack-plugin": "^3.2.0",
"html-withimg-loader": "^0.1.16",
"jsonc": "^2.0.0",
"less": "^3.10.2",
"less-loader": "^5.0.0",
"mini-css-extract-plugin": "^0.8.0",
"mocker-api": "^1.8.1",
"optimize-css-assets-webpack-plugin": "^5.0.3",
"postcss-loader": "^3.0.0",
"style-loader": "^1.0.0",
"terser-webpack-plugin": "^1.4.1",
"uglifyjs-webpack-plugin": "^2.2.0",
"url-loader": "^2.1.0",
"vue-loader": "^15.7.1",
"vue-style-loader": "^4.1.2",
"vue-template-compiler": "^2.6.10",
"webpack": "^4.39.2",
"webpack-cli": "^3.3.7",
"webpack-dev-server": "^3.8.0"
}
}
const path = require('path');
const webpack = require('webpack');
// script、link动态添加每次compile后的hash,防止引用缓存的外部文件问题; 自动创建html入口文件
const HtmlWebpackPlugin = require('html-webpack-plugin');
// 用terser-webpack-plugin替换掉uglifyjs-webpack-plugin解决uglifyjs不支持es6语法问题
const TerserJSPlugin = require('terser-webpack-plugin');
// 此模块至少需要Node v6.9.0和webpack v4.0.0 混淆代码
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
// 这个插件将CSS提取到单独的文件中 支持按需加载CSS和SourceMaps 建立在webpack v4上
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// 用于优化、压缩CSS资源
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin');
// 打包时将之前打包的目录里的文件先清除干净,再生成新的
const {CleanWebpackPlugin} = require('clean-webpack-plugin');
//mock数据
const apiMocker = require('mocker-api');
const VueLoaderPlugin = require('vue-loader/lib/plugin');
//获取 npm run 后面的命令
const lifecycle = process.env.npm_lifecycle_event;
//npm run 的文件名
const project = lifecycle.split('-')[0];
//npm run 的环境名
const proMode = lifecycle.split('-')[1] === 'te';
const envMode = lifecycle.split('-')[1];
const webpackConfig = {
mode: proMode ? 'production' : 'development',
//打包入口为每个项目的main.js
entry: path.resolve(__dirname, `${project}/main.js`),
output: {
//打包后的文件目录为各自项目名+Dist
path: path.resolve(__dirname, `${project}Dist`),
//打包后源代码映射
// devtool: proMode ?'cheap-module-eval-source-map':'hidden-source-map',
// devtool: "inline-source-map",
//打包后的出口js目录
filename: 'js/[name].[hash].js',
//分块打包的js目录
chunkFilename: proMode ? 'js/[name].[contenthash].bundle.js' : 'js/[name].bundle.js',
},
module: {
rules: [
{
test: /\.vue$/,
exclude: /node_modules/,
use: {
loader: 'vue-loader'
}
},
{
test: /\.(le|c)ss$/i,
use: [
proMode ? MiniCssExtractPlugin.loader :
'vue-style-loader',
'css-loader',
'postcss-loader',
'less-loader',
],
},
{
test: /\.html$/i,
use: [
'html-withimg-loader'
]
},
{
test: /\.(png|jpg|gif)$/i,
use: [
{
loader: 'url-loader',
options: {
limit: 4096,
name: 'img/[name].[contenthash].[ext]'
},
},
],
},
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
}
]
},
//webpack-dev-server 配置npm run 时启动本地服务
devServer: {
contentBase: `./${project}Dist`,
inline: true //实时刷新
},
//优化
optimization: {
// 分块
splitChunks: {
chunks: 'all',
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all'
},
}
}
},
plugins: [
new CleanWebpackPlugin(),
//定义插件—— 在项目中可以读取到
new webpack.DefinePlugin({
'baseUrl':proMode ? 'https:www.baidu.com':JSON.stringify('localhost')
}),
new HtmlWebpackPlugin({
title:'webpack练习',
filename: 'index.html',
template: `${project}/index.html`,
// 对 html 文件进行压缩
minify: {
//是否对大小写敏感,默认false
caseSensitive: false,
//是否简写boolean格式的属性如:disabled="disabled" 简写为disabled 默认false
collapseBooleanAttributes: true,
//是否去除空格,默认false
collapseWhitespace: true,
//是否压缩html里的css(使用clean-css进行的压缩) 默认值false;
minifyCSS: true,
//是否压缩html里的js(使用uglify-js进行的压缩)
minifyJS: true,
//是否移除注释 默认false
removeComments: true,
//Prevents the escaping of the values of attributes
preventAttributesEscaping: true,
//是否移除属性的引号 默认false
removeAttributeQuotes: true,
//从脚本和样式删除的注释 默认false
removeCommentsFromCDATA: true,
//是否删除空属性,默认false
removeEmptyAttributes: false,
// 若开启此项,生成的html中没有 body 和 head,html也未闭合
removeOptionalTags: false,
//删除多余的属性
removeRedundantAttributes: true,
//删除script的类型属性,在h5下面script的type默认值:text/javascript 默认值false
removeScriptTypeAttributes: true,
//删除style的类型属性, type="text/css" 同上
removeStyleLinkTypeAttributes: true,
//使用短的文档类型,默认false
useShortDoctype: false,
}
}),
new VueLoaderPlugin()
],
//目录映射
resolve: {
alias: {
'@assets': path.resolve(__dirname, `${project}/assets`),
'@mixins': path.resolve(__dirname, `${project}/mixins`),
'@tools': path.resolve(__dirname, `${project}/tools`),
'@components': path.resolve(__dirname, `${project}/components`),
}
}
};
if (proMode) {
webpackConfig.optimization.minimizer = [
//混淆语法
new UglifyJsPlugin({
chunkFilter: (chunk) => {
if (chunk.name === 'vendor') {
return false;
}
return true;
},
//去掉控制台日志
uglifyOptions: {
compress: {
drop_console: true
}
}
}),
new OptimizeCssAssetsPlugin({})
];
// webpackConfig.optimization.minimizer = [new TerserJSPlugin({}),
// new OptimizeCssAssetsPlugin({}),];
webpackConfig.plugins.push(
new MiniCssExtractPlugin({
filename: proMode ? '[name].css' : '[name].[hash].css',
chunkFilename: proMode ? '[id].css' : '[id].[hash].css',
})
)
} else {
// 热更新模块
webpackConfig.plugins.push(new webpack.HotModuleReplacementPlugin());
webpackConfig.devtool = 'inline-source-map';
if (envMode == 'mock') {
//mock环境,启用mock代理服务
webpackConfig.devServer.before = (app) => {
apiMocker(app, path.resolve(`${project}/mock/api.js`));
};
//非mock匹配项走测试环境
webpackConfig.devServer.proxy = process.baseUrl;
}
}
module.exports = webpackConfig;
在当今的专业环境中,项目经理需要戴上各种帽子,在管理团队的日常功能和理解大局策略之间切换。正因为如此,项目经理对组织变得更有价值,并且他们对技能和战略角色的需求在全球范围内不断增长。但这也提出了一个问题:如何在如此高压的环境中成为更好的项目经理?
随机产生规定范围内的整数,然后再产生相同范围内的整数,两者相同时,则暂停。所用知识:Math.random() * num: 产生从0到num的随机数,Math.floor(): 向下取整,简单的DOM操作等
我马上就要毕业了没有开发经验怎么办?我投递了 N 多公司全部没有给工作机会,有的给了面试机会也是没有下文了怎么办?我简历上什么东西都没有,要不要伪造一个工作经历呢?
项目经理这个神奇的职位,改变了我很多工作处事的方式,从前性情纯真的耿直boy,现在变成了人鬼皆爱的老油条, 以下是我当了项目经理之后明白的10件事, 如有雷同,真是太巧。
pm2 大家应该都知道,主要是用来管理 node 进程,但是同样可以用来部署前端代码。也可以手动添加 public key 到服务器上的 ~/.ssh/authorized_keys,
我不是专业的项目经理,这里不讨论大型项目管理的事情。我们比较常遇到的可能是小型的长周期项目,比如2-4个人,做半年甚至一年的项目。这种项目通常不会有专职的项目经理
通过 attachShadow 这个方法生成一个shadow root 即shadow的根节点,然后在这个根节点下面通过循环语句添加水印,利用position为absolute进行排版,使其铺满容器
我相信每个接受过老项目的程序员可能都吐槽过“前人的代码都是屎”。一个已经有些年头的项目,几乎肯定可以看到——到处拷贝来拷贝去的代码,随处可见的拼写错误,头重脚轻的函数……
近几年随着微服务化项目的崛起,逐渐成为许多公司中大型分布式系统架构的主流方式,而今天所说的 RPC 在这其中扮演着至关重要的角色。随着这段日子公司项目微服务化的演进,发现在日常开发中都在隐式或显式的使用 RPC
首先搭建vue项目,lint选择ESLint + Prettier,配置方式选择In dedicated config files。具体搭建过程这里就不赘述了,如果不熟悉的同学可以点击这里。配置 Stylelint,目前还没有stylelint选项,需要我们自己安装相关的 npm 包
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!