安装本地的webpackcss
yarn add webpack webpack-cli -D
复制代码
npx webpack
npx webpack --mode production // 默认为生产环境 会进行压缩打包
npx webpack --mode development
复制代码
webpack_require 至关因而webpack本身实现的一套模块化的机制html
默认配置文件名称为 webpack.config.jsvue
module.exports = {
mode: 'development', // 模式 默认两种 production development
entry: './src/index.js', // 入口
output: {
filename: 'bundle.[hash:8].js', // 出口 [hash:8]显示8位hash值
path: path.resolve(__dirname, 'build') // path必须是一个绝对路径 path.resolve帮咱们把相对路径解析成绝对路径
},
}
复制代码
在webpack-cli/bin/config-yargs中能够看到有这样一行 defaultDescription: "webpack.config.js or webpackfile.js" 即配置文件名称为webpack.config.js or webpackfile.js 固然咱们也能够手动指定配置文件的名称node
npx webpack --config filename
复制代码
也能够经过在package.json中的script里配置jquery
"scripts":{
"build": "webpack --config webpack.config.js" // webpack.config.js可改成自定义文件名
},
复制代码
npm run build
复制代码
若是必定要手动传参也能够经过多加两个-webpack
"scripts":{
"build": "webpack" // webpack.config.js可改成自定义文件名
},
复制代码
npm run build -- --config webpack.config.js
复制代码
到目前为止,咱们的配置依然很弱,只能打包js文件,接下来咱们继续添加更多的配置es6
下面咱们但愿可以经过http://localhost 这样的方式来启动一个服务, 咱们能够经过webpack内置的一个服务 webpack-dev-server (内部是经过express实现的)web
yarn add webpack-dev-server -D
复制代码
如今咱们能够经过express
npx webpack-dev-server
复制代码
固然也一样能够经过package.json设置npm
"scripts": {
"dev": "webpack-dev-server",
"build": "webpack --config webpack.config.js"
},
复制代码
而后执行
npm run dev
复制代码
同时咱们能够给在webpack.config.js中对webpack-dev-server进行配置
devServer: { // 开发服务器的配置
port: '3000',
progress: true,
contentBase: './build',
open: true
},
复制代码
指望:动态生成build/index.html, 并把打包后的文件引入到index.html
在src目录下建index.html,这时咱们须要使用插件HtmlWebpackPlugin,plugin的用法大都相同,HtmlWebpackPlugin是一个类,new一下就能够了
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html', // template文件
filename: 'index.html', // 生成的template文件名称 默认为index.html
hash: true, // 在生成的html中添加引用hash
minify: {
removeAttributeQuotes: true, // 去除双引号
collapseWhitespace: true, // 去除空行
}
}),
],
复制代码
到这里能够看到咱们既能够经过在配置output的时候经过filename: bundle.[hash:8].js 来给生成文件添加hash,也能够经过HtmlWebpackPlugin的配置hash来实现,二者添加hash的方式分别为 bundle.12345678.js和 bundle?12345678
而经过filename: bundle.[hash:8].js这种方式实现,咱们还须要再作一步,就是在每次从新打包的时候把旧的文件删除 // todo
咱们知道,webpack默认只支持js模块,那么咱们怎么处理css/less/scss等模块呢?这时候就须要loader上场了
You may need an appropriate loader to handle this file type.
复制代码
module: { // 模块
rules: [ // 规则
// css-loader 主要用来解析@import这种语法
// style-loader 把样式插入页面
// loader特色,功能单一 多个loader能够协做
// 一个loader可使用字符串,多个可使用数组, 须要传入参数时可使用对象方式
// loader的顺序,默认为从右向左, 从下到上执行 webpack选择了compose方式
// {
// test: '/\.css$/', use: [
// { loader: 'css-loader', options: {} } // 对象方式
// ]
// },
{ test: /\.css$/, use: ['style-loader', 'css-loader'] },
]
},
复制代码
less、sass文件同理, 以scss文件为例:
{
test: /\.css$/, use: [
{ loader: 'style-loader', options: { insertAt: 'top' } }, // 对象方式 insertAt插入位置
{ loader: 'css-loader', options: {} },
]
},
{ test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] },
复制代码
webpack4中,css抽离须要插件 mini-css-extract-plugin (注意再也不是extract-text-webpack-plugin)
new miniCssExtractPlugin({
filename: 'main.css', // 抽离出的css的文件名
}),
复制代码
同时在module.rules中作以下修改以免重复插入:
- // { test: /\.scss$/, use: ['style-loader', 'css-loader', 'sass-loader'] },
+ { test: /\.scss$/, use: [miniCssExtractPlugin.loader, 'css-loader', 'sass-loader'] },
复制代码
咱们可使用postcss-loader autoprefixer来实现
- // { test: /\.scss$/, use: [miniCssExtractPlugin.loader, 'css-loader', 'sass-loader'] },
+ { test: /\.scss$/, use: [miniCssExtractPlugin.loader, 'css-loader', 'postcss-loader', 'sass-loader'] },
复制代码
在根目录下新建postcss.config.js
module.exports = {
plugins: [
require('autoprefixer'), // 自动添加前缀
]
}
复制代码
此时咱们设置mode为production,发现js和html都已是压缩过的了,但是css文件却没有。咱们这里引入另一个插件:optimize-css-assets-webpack-plugin来优化css资源
let OptimizeCss = require('optimize-css-assets-webpack-plugin');
plugins: [
...,
new OptimizeCss(),
]
复制代码
固然咱们也能够经过uglifyjs-webpack-plugin来压缩咱们的js文件
let UglifyjsPlugin = require('uglifyjs-webpack-plugin');
plugins: [
...,
new UglifyjsPlugin(),
]
复制代码
咱们但愿打包后的文件能够把es6语法转为es5,能够经过babel-loader帮咱们实现
// src/a.js
console.log('this is a');
const fn = () => {
console.log('fn');
}
复制代码
安装babel依赖模块
yarn add babel-loader @babel/core @babel/preset-env -D
复制代码
{
test: /\.js|jsx$/, use:
{
loader: 'babel-loader', options: {
presets: ['@babel/preset-env']
}
}
},
复制代码
如今写es6的语法没有问题了,可是咱们有可能用到es7的语法, 好比类的写法,这时候咱们还须要借助一个插件:@babel/plugin-proposal-class-properties 又好比装饰器的写法,咱们能够借助@babel/plugin-proposal-decorators来实现
{
test: /\.js|jsx$/, use:
{
loader: 'babel-loader', options: {
presets: ['@babel/preset-env'],
plugins: [
["@babel/plugin-proposal-decorators", { "legacy": true }], // 支持es7的装饰器的写法 要放在前面
'@babel/plugin-proposal-class-properties', // 支持es7的类的写法
]
}
}
},
复制代码
这里须要注意的是@babel/plugin-proposal-decorators要放在@babel/plugin-proposal-class-properties前面。
babel只会帮咱们把es6新的语法转成es5,可是对于新的API如:promise, generater 等咱们还须要借助一个包 @babel-polyfill(可是比较大) 同时咱们能够借助一个插件--@babel/plugin-transform-runtime 作了必定优化,如代码抽离
yarn add eslint eslint-loader
复制代码
{
test: /\.js|jsx$/,
use: {
loader: 'eslint-loader',
options: {
enforce: 'pre', // pre post
}
}
},
复制代码
接下来就可使用本身配置好的.eslintrc.json文件(放在根目录下),固然咱们也能够到eslint官网,手动进行配置,而后下载eslintrc.json,只要加个.就好了。
import $ from 'jquery';
console.log($)
console.log(window.$) // undefined
复制代码
import $ from 'expose-loader?$!jquery';
console.log($)
console.log(window.$) // undefined
复制代码
{
test: require.resolve('jquery'),
use: 'expose-loader?$'
},
// index.js
console.log(window.$)
复制代码
let webpack = require('webpack');
new webpack.ProvidePlugin({ // 在每一个模块中都注入$
$: 'jquery',
}),
// index.js
console.log($); // 均可以访问
console.log(window.$)
复制代码
externals: { // 外部引入,不须要打包
jquery: '$',
},
// index.js
import $ from 'jquery'; // 虽然引入可是不会再打包
console.log($);
复制代码
咱们使用图片的场景有两种:
// index.js
let img = new Image();
img.src = require('./logo.png');
document.body.appendChild(img);
复制代码
这时咱们须要借助 file-loader 了
{
test: /\.png|jpg|gif|jpeg$/,
loader: 'file-loader',
options: {
}
},
复制代码
// index.js
import logo from './logo.png'; // 返回一个新的文件 好处是能够重命名图片
let img = new Image();
img.src = logo;
document.body.appendChild(img);
// a.css
body{
color: yellow;
background: url('./logo.png') no-repeat;
}
复制代码
ok,发现前两种都没有什么问题,但是第三种直接写在html中的却不行
<body>
<img src='./logo.png' alt=""/>
<!-- 模版 -->
</body>
复制代码
处理直接写在html里的图片,还须要用到另外一个loader:
{
test: /\.html/,
use: 'html-withimg-loader'
},
复制代码
从新启动就行了。
若是想要作更多的限制呢,好比说对打包图片大小的限制打包成base64以减小http请求(base64会比源文件大1/3左右),咱们可使用 url-loader
{
test: /\.png|jpg|gif|jpeg$/,
loader: 'url-loader',
options: {
limit: 4 * 1024, // 图片大小限制值
outputPath: '/img/', // 输出目录
publicPath: 'http://58.com' // 添加打包后的图片域名
}
},
复制代码
基本配置以下:
let path = require('path');
let HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
home: './src/index.js',
other: './src/other.js',
},
output: {
filename: '[name].js', // name为变量,根据entry的命名生成对应打包后的文件名称
path: path.resolve(__dirname, 'dist'),
},
plugins: [
new HtmlWebpackPlugin({ // 这里须要new多个HtmlWebpackPlugin
template: './src/index.html',
filename: 'home.html',
chunks: ['home'] // html依赖,决定了打包后的哪些文件插入该模版中, 能够写多个,且有顺序
}),
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'other.html',
chunks: ['other', 'home']
}),
],
}
复制代码
// devtool: 'source-map', // 增长映射文件 会单独生成一个sourcemap文件,出错了会标示当前出错的列和行 特色 大 全
devtool: 'eval-map',
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'home.html',
}),
],
复制代码
output: {
filename: '[name].js', // name为变量,根据entry的命名生成对应打包后的文件名称
path: path.resolve(__dirname, 'dist'),
},
watch: true, // 实时编译打包
watchOptions: { // 监控选项
poll: 1000, // 每秒访问多少次
aggregateTimeout: 500, // 防抖
ignored: /node_modules/
},
复制代码
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
filename: 'home.html',
}),
new CleanWebpackPlugin('./dist'), // 传入要删除的目录 也可传数组
new CopyWebpackPlugin([{ from: './src/static', to: './dist' }]), //须要拷贝的目录 必须是arr
new webpack.BannerPlugin('make 2019 by beth.miao'),
],
复制代码
proxy: {
'/api': {
target: 'http://localhost:3001',
pathRewrite: { '/api': '' }
}
}
复制代码
resolve: { // 解析第三方包 common
modules: [path.resolve('node_modules')],
// mainFields: ['style', 'main'],
// mainFiles: '',
alias: {
bootstrap: 'bootstrap/dist/css/bootstrap.css',
},
extensions: ['.js', '.css', '.json', 'vue'], // 引入路径后缀名处理
},
复制代码