目前前端最主流,应用最广的webpack总结下
目前常用的构建工具
但是现在大部分公司都需要自己能搞定脚手架,所以大家还是能自己搭建为好
loader
webpack loader 将所有类型的文件,转换为应用程序的依赖图(和最终的 bundle)可以直接引用的模块。
配置中 loader 有两个目标:
test 属性,用于标识出应该被对应的 loader 进行转换的某个或某些文件。
use 属性,表示进行转换时,应该使用哪个 loader。
配置参数
配置参数
$ mkdir webpack-demo
$ cd webpack-demo
$ npm init -y // -y的意思是默认安装
新建四个文件,分别是webpack.base.js(基础环境),webpack.dev.js(开发环境),webpack.prod.js(生产环境),.gitignore(git忽略文件)
这时候我们的文件目录为
// 模块管理和打包工具
$ npm install webpack@3 -D
// 监听代码自动刷新(注意@3版本对应webpack@4)
$ npm install webpack-dev-server@2 -D
// 安装merge
$ npm i webpack-merge -D
// 安装html处理
$ npm i html-webpack-plugin -D
// 清除插件
$ npm i clean-webpack-plugin -D
// copy 插件
$ npm i copy-webpack-plugin -D
// 安装dev open-browser
$ npm i open-browser-webpack-plugin -D
// 安装 lodash
$ npm install lodash -S
配置webpack.base.js
/**
* @component webpack.base.js
* @description 基础环境
* @time 2018/3/8
* @author **
*/
const webpack = require('webpack');
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 生成html
const CleanWebpackPlugin = require('clean-webpack-plugin'); // 清除dist
const CopyWebpackPlugin = require('copy-webpack-plugin'); // copy
function resolve(dir) {
return path.join(__dirname, dir);
}
module.exports = {
entry: {
app: './src/index.js',
vendor: [
'lodash'
]
},
resolve: {
extensions: [' ', '.js', '.json', '.jsx', '.css', '.less','.json'],
modules: [resolve( "src"), "node_modules"], //绝对路径;
},
module: {
},
plugins: [
new CleanWebpackPlugin(['dist']),
new CopyWebpackPlugin([{
from: "./public",
to: "",
force: true
}]),
new HtmlWebpackPlugin({
filename: 'index.html',//输出的html路径
template: './public/index.html', //html模板路径
chunks: ['app', 'vendor', 'manifest'],
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyCSS: true,
minifyJS: true,
minifyURLs: true,
}
}),
new webpack.HashedModuleIdsPlugin(), // 修复vendor hash
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: Infinity
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest', // 指定公共 bundle 的名称。
minChunks: Infinity
})
]
};
配置webpack.dev.js
/**
* @component webpack.dev.js
* @description 开发环境
* @time 2018/3/8
* @author **
*/
const webpack = require('webpack');
const path = require('path');
const merge = require('webpack-merge');
const OpenBrowserPlugin = require('open-browser-webpack-plugin');
const base = require('./webpack.base.js');
function resolve (dir) {
return path.join(__dirname, dir)
}
// 端口
const port = 8080;
module.exports = merge(base, {
output: {
filename: 'static/js/[name].js', //
path: resolve('dist'), // 输出的文件地址
publicPath: ''
},
devtool: 'inline-source-map',
module: {
},
devServer: {
contentBase: './dist',
compress: true,
port: port,
historyApiFallback: true,//不跳转
inline: true//实时刷新
},
plugins: [
new webpack.NamedModulesPlugin(),
new webpack.HotModuleReplacementPlugin(),
new OpenBrowserPlugin({ url: 'http://localhost:'+port }),
],
});
配置webpack.prod.js
/**
* @component webpack.prod.js
* @description 生产环境
* @time 2018/3/8
* @author **
*/
const webpack = require('webpack');
const path = require('path');
const merge = require('webpack-merge');
const base = require('./webpack.base.js');
function resolve (dir) {
return path.join(__dirname, dir)
}
module.exports = merge(base, {
output: {
filename: 'static/js/[name].[hash:7].js', //
path: resolve('dist'), // 输出的文件地址
publicPath: './'
},
devtool: 'source-map',
module: {
},
plugins: [
new webpack.optimize.UglifyJsPlugin({ // 压缩JS
compress: {
warnings: false,
comparisons: false,
},
mangle: {
safari10: true,
},
output: {
comments: false,
ascii_only: true,
},
sourceMap: true,
}),
]
});
src新增index.js
import _ from 'lodash';
function component() {
var element = document.createElement('div');
// Lodash, now imported by this script
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
element.classList.add('hello');
return element;
}
document.body.appendChild(component());
public新增index.html
Getting Started
修改package.json
"scripts": {
"dev": "webpack-dev-server --config webpack.dev.js",
"build": "webpack --config webpack.prod.js"
},
分别执行 npm run dev(开发) / npm run build(发布)
演示目的,我们使用开发演示修改代码。
// 安装相关loader
$ npm install style-loader css-loader less-loader postcss-loader postcss-flexbugs-fixes -D
$ npm i autoprefixer -D
$ npm i less -D
// 将css分离出js
$ npm i extract-text-webpack-plugin -D
配置webpack.prod.js
const webpack = require('webpack');
const autoprefixer = require('autoprefixer');
const path = require('path');
const merge = require('webpack-merge');
const ExtractTextPlugin = require("extract-text-webpack-plugin"); // 分离css
const base = require('./webpack.base.js');
function resolve (dir) {
return path.join(__dirname, dir)
}
module.exports = merge(base, {
output: {
filename: 'static/js/[name].[hash:7].js', //
path: resolve('dist'), // 输出的文件地址
publicPath: './'
},
devtool: 'source-map',
module: {
rules: [
{
test: /\.css$/,
loader: ExtractTextPlugin.extract({
fallback: {
loader: require.resolve('style-loader'),
options: {
hmr: false,
},
},
use: [
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
minimize: true,
sourceMap: true,
},
},
{
loader: require.resolve('postcss-loader'),
options: {
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
],
},
},
],
}),
},
{
test: /\.less$/,
loader: ExtractTextPlugin.extract({
fallback: {
loader: require.resolve('style-loader'),
options: {
hmr: false,
},
},
use: [
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
minimize: true,
sourceMap: true,
},
},
{
loader: require.resolve('postcss-loader'),
options: {
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
],
},
},
{
loader: require.resolve('less-loader'),
options: {
importLoaders: 2,
minimize: true,
sourceMap: true,
},
},
],
}),
// Note: this won't work without `new ExtractTextPlugin()` in `plugins`.
},
]
},
plugins: [
new webpack.optimize.UglifyJsPlugin({ // 压缩JS
compress: {
warnings: false,
comparisons: false,
},
mangle: {
safari10: true,
},
output: {
comments: false,
ascii_only: true,
},
sourceMap: true,
}),
new ExtractTextPlugin({
filename: "static/css/[name].[hash:7].css",
allChunks: true
}),
]
});
配置webpack.dev.js
const webpack = require('webpack');
const autoprefixer = require('autoprefixer');
const path = require('path');
const merge = require('webpack-merge');
const OpenBrowserPlugin = require('open-browser-webpack-plugin');
const base = require('./webpack.base.js');
function resolve (dir) {
return path.join(__dirname, dir)
}
// 端口
const port = 8080;
module.exports = merge(base, {
output: {
filename: 'static/js/[name].js', //
path: resolve('dist'), // 输出的文件地址
publicPath: ''
},
devtool: 'inline-source-map',
module: {
rules: [
{
test: /\.css$/,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
},
},
{
loader: require.resolve('postcss-loader'),
options: {
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
],
},
},
],
},
{
test: /\.less$/,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
},
},
{
loader: require.resolve('postcss-loader'),
options: {
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
browsers: [
'>1%',
'last 4 versions',
'Firefox ESR',
'not ie < 9', // React doesn't support IE8 anyway
],
flexbox: 'no-2009',
}),
],
},
},
{
loader: require.resolve('less-loader'),
options: {
importLoaders: 2,
},
},
],
},
]
},
devServer: {
contentBase: './dist',
compress: true,
port: port,
historyApiFallback: true,//不跳转
inline: true//实时刷新
},
plugins: [
new OpenBrowserPlugin({ url: 'http://localhost:'+port }),
],
});
src修改
新增index.css, test.less
/**index.css**/
body {
background-color: aqua;
}
/**test.less**/
.hello {
color: red;
transition: all .5s;
}
/**index.js新增**/
import './index.css'
import './test.less'
npm run build查看打包dist文件夹
// image和font处理
$ npm i file-loader url-loader -D
//减少打包的时候重复代码
$ npm i babel-runtime -S
$ npm i babel-plugin-transform-runtime -D
//安装babel相关
$ npm i babel-loader -D //安装babel-loader
$ npm i babel-core -D //安装babel核心
$ npm i babel-preset-es2015 -D //支持ES2015
$ npm i babel-preset-react -D //支持jsx
$ npm i babel-preset-stage-0 -D //支持ES7
//安装react
$ npm i react -S
$ npm i react-dom -S
webpack.base.js新增module,修改entry
entry: {
app: './src/index.js',
vendor: [
'react',
'react-dom'
]
},
module: {
rules: [
{
test: /\.(js|jsx)?$/,
loader: 'babel-loader',
exclude: /node_modules/,
include: [resolve('src'), resolve('test')]
},
{
test: /\.(png|svg|jpg|gif|jpeg)$/, use:
[{
loader: 'url-loader',
options: {
fallback: 'file-loader',
limit: 8192,
outputPath: 'static/images/',
name: '[name]_[hash:7].[ext]',
}
}]
},
{
test: /\.(woff|woff2|eot|ttf|otf)$/, use:
[{
loader: 'file-loader',
options: {
outputPath: 'static/fonts/',
name: '[name]_[hash:7].[ext]',
}
}]
}
]
},
在public/index.html