命令
npx webpack
一般来说,调用 Mocha ,只能在项目脚本和 package.json 的scripts字段里面, 如果想在命令行下调用,必须像下面这样。
# 项目的根目录下执行
$ node-modules/.bin/mocha --version
npx 就是想解决这个问题,让项目内部安装的模块用起来更方便,只要像下面这样调用就行了。
$ npx mocha --version
npx 的原理很简单,就是运行的时候,会到node_modules/.bin路径和环境变量$PATH里面,检查命令是否存在。
由于 npx 会检查环境变量$PATH,所以系统命令也可以调用
注意,Bash 内置的命令不在$PATH里面,所以不能用。比如,cd是 Bash 命令,因此就不能用npx cd。
打包支持模块化
| 打包 | 运行 |
|---|---|
| npx webpack | 写个index.html导入打包后的js |
| htmlWebpackPlugin | webpack-dev-server |
css打包
- MiniCssExtractPlugin 抽离
- autoprefixer postcss-loader 在样式的类前加浏览器前缀
- optimize-css-assets-webpack-plugin 压缩
es6语法
- @babel/preset-env 大集合
- @balbel/code
- @babel/plugin-transform-runtime 打包include语法
eslint
- 官网上下载配置
- 设置先执行enforce: 'pre'/post
配置命令
"build": "webpack",
"dev": "webpack-dev-server --open --port 3000 --hot "
全局变量(jquery cdn)
// 在文件中处理
import $ from 'expose-loader?$!jquery'
// 打包配置中匹配处理
{
test: require.resolve('jquery'),
use: 'expose-loader?$',
}
// 使用ProvidePlugin分别插入
const webpackPlugin = new webpack.ProvidePlugin({
$: 'jquery'
})
//引入jquery会忽略掉(已经在cdn引入了)
externals: {
jquery: '$'
},
图片
1.js import 图片 2.css 导入到js中,直接使用 3.html中引入图片html-withimg-loader
file-loader和url-loader
url-loader //做一个限制 当小于多少k 用base64来转化 base64文件可以减少http请求 但是比原文件大3分之1 // 否则用file-loader来产生真实的图片
打包分类和添加域名
options: {
limit: 1, // 文件大小限制
//输出的路径
outputPath: 'img/',
//只在图片中有一个公共的路径
publicPath: 'http:/111'
}
source-map源码映射(调试使用)
增加 devtool 源码映射 可以很方便的调试源代码
// 列是指定位到错误的代码列
// 大 全
devtool:'source-map',
// 不会单独生成一个文件 但会显示行和列
devtool: 'eval-source-map',
// 不会产生单独列 但会生成一个映射文件
devtool: 'cheap-module-source-map',
// 不会单独生成文件 集成在打包文件中 也不产生列
devtool: 'cheap-module-eval-source-map',
三个其他的小插件
// 1. cleanWebpackPlugin
// 每次打包会把dist目录下的文件都删除 重新打包
// 2. copyWebpackPlugin
//拷贝文件
const copyPlugin = new copyWpackPlugin(
//接受一个数组 可以多个文件
[{from:'./doc',to:'./'}]
)
// 3. bannerPlugin
// bannerPlugin 版权声明
const bannerPlugin = new webpack.BannerPlugin('make by hanke ,i will become success!')
// 前两个 需要第三方模块 第三个内置
webpack跨域
//跨域问题的设置
devServer:{
//这是 服务器为 /api/user
/* proxy : {
'/api':'http://localhost:3500'
} */
// /user的用法
proxy: {
// 1.重写的方式 把请求代理到express服务器上
'/api': {
target: 'http://localhost:3500',
pathRewrite: {
'/api':'/'
}
}
}
//2.前端只想单纯模拟方法
before(app){ //提供的方法 相当于钩子
//写这些代码就不存在跨域问题
app.get('/user',(req,res)=>{
res.json({
name: 'myname-before'
})
})
}
//3.有服务端,但是不用代理来处理 在服务器端开启webpack 端口用服务端端口
/* 服务端代码
//需要使用中间件webpack-dev-middleware
let middle = require('webpack-dev-middleware')
let config = require('./webpack.config.js')
let compiler = webpack(config)
app.use(middle(compiler))
*/
}
resolve配置
resolve: {
//指定解析的模块
modules: [path.resolve('node_modules')],
//或者用 mainFields 入口的字段 先找style 再找main
// mainFiles: [],//入口文件的名字 默认找index.js
mainFields: ['style','main'],
//扩展名 可以省略 需配置 extensions 依次解析
extensions: ['.js','.css','.json']
//别名 如 vue的vue-runtime和那个@
// alias: {
// bootstrap: 'bootstrap/dist/css/bootstrap.css'
// }
},
环境变量
// 判断开发环境的插件 DefinePlugin
const definePlugin = new webpack.DefinePlugin({
DEV: JSON.stringify('production'),
FLAG: 'true',
EXPORESSION: '1+1'
})
区分环境
npm run build -- --config webpack.dev.js
webpack-merge
let {smart} = require('webpack-merge')
let base = require('./webpack.config.js')
module.exports = smart(base,{
mode:'production'
})
忽略引入
//webpack自带的IgnorePlugin 忽略掉moment中locale引入的东西
const ignorePlugin = new webpack.IgnorePlugin(/\.\/locale/,/moment/)
import moment from 'moment'
//加入 ignorePlugin之后就不起作用了
// moment.locale('zh-cn')
//自己手动引入所需要的语言包
import 'moment/locale/zh-cn'
let r = moment().endOf('day').fromNow()
动态引入链接库
//webpack自带的 config.js中引入打包好的库
const dllReferencePlugin = new webpack.DllReferencePlugin({
manifest: path.resolve(__dirname,'dist','manifest.json')
})
//webpack自带插件 打包成动态链接库 事先写好的webpack.config.xxx.js
//导出 manifest.json 以及 _dll_react.js
const dllPlugin = new webpack.DllPlugin({ //name==library
name: '_dll_[name]',
//manifest.json就是一个任务清单
path: path.resolve(__dirname,'dist','manifest.json')
})
module.exports = {
mode: 'development',
entry: {
// test: '.c/test.js'
react: ['react','react-dom']
},
output: {
filename: '_dll_[name].js', //打包后的文件名
path: path.resolve(__dirname,'dist'),
//指定 var a = '...'
library: '_dll_[name]',
//配置commonjs 会变成export["ab"] 配置umd会变成umd模式 可配置 commonjs var this 主要用var(默认就是)
//braryTarget: 'var'
},
plugins: [
dllPlugin
]
}
多线程打包
// 模块 happypack 来多线程打包webpack 进程(node中线程与进程关系) 打包文件会加快(文件很小时可能会变慢)
const Happypack = require('happypack')
// happyplugin配置
const happyPlugin = new Happypack({
id:'js',
use: [{
loader:'babel-loader',
options: {
presets: [
'@babel/preset-env',
'@babel/preset-react',
]
}
}]
})
rules:[
{
test: /\.js$/,
//指定一个id 可能css也需要多线程打包
use: 'Happypack/loader?id=js',
}
]
webpack优化
tree-shaking
scope hosting
import calc from './test'
// import 在生产环境下会自动清除没用的东西
// 相当于tree-shaking 没用代码自动删除
// import 可以 但是 require就不行
console.log(calc.sum(1,2))
// scope hosting 作用域提升
let a = 1
let b = 2
let c = 3
let d = a+b+c //webpack会自动省略可以简化的代码
console.log(d+'------')
抽离公共代码
optimization: {
splitChunks:{ //分割代码块
cacheGrops:{ //缓存组
common:{ //公共模块
chunks: 'initial', //入口从哪找
minSize: 0 , //大于0个字节
minChunks: 0 //引用0次
}
},
vendor: { //抽离第三方模块
priority: 1, //先抽离第三方模块
test: de_modules/, //引入
chunks: 'initial', //入口从哪找
minSize: 0 , //大于0个字节
minChunks: 0 //引用0次
}
}
},
热更新所需插件
// 热更新所需插件
const hotPlugin = new webpack.HotModuleReplacementPlugin()
const namePlugin = new webpack.NamedModulesPlugin() //打印名字
devServer:{
//热更新
hot: true,
port: 3000,
open: true,
contentBase: './dist'
},
告诉那个文件更新了
import str from './source.js'
console.log(str)
if(module.hot) {
module.hot.accept('./source.js',()=>{
//import只能写在页面的顶端
let str =require('./source.js')
console.log(str.default)
})
}
tabable
- 累加器
function getSum(total, num) {
return total + Math.round(num);
}
function myFunction(item) {
document.getElementById("demo").innerHTML = numbers.reduce(getSum, 0);
}
将多个方法放在对象的属性中,调用call等时循环执行
// 同步调用
/*
SyncHook
SyncBailHook 中断
SyncWaterfallHook 下个参数为上个结果
SyncLoopHook 循环多次
*/
// 异步调用
/*
AsyncParallelHook
// 方法
tapAsync callAsync(从参数中取最终函数,当调用一次时done一次计数,达到时调用最终函数)
promise(会返回属性中返回的promise)
*/
webpack手写
npm link // 链接到全局下,在全局node_module下生成命令当前目录下的快捷方式
npm link 文件名 // 'bin': {'命令':'文件名'},链接到当前node_module
// 1.先拿到入口文件路径和内容,
this.entry = config.entry
this.root = process.cwd() //表示 工作路径
let content = fs.readFileSync(modulePath,'utf-8')
// 2.通过ast解析内容中require(内容)和路径并替换成自己的方法和加’src’,返回解析编译后的内容和入口文件的附属模块数组
//babelon 把源码解析成AST
//@babel/traverse 遍历节点
//@babel/types 节点替换
//@babel/generator 生成
{
'src/a.js':'let str = __webpack_require("./src\\a.js");\n console.log(str);'
}
['./src\\a.js']
// 3.通过附属模块数组递归调用3>>>1>>>2>>>3