Open Manjushaka opened 5 years ago
Asset Management: 1) Loading css:
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
},
2) loading images:
{
test: /\.(png|svg|jpg|jpeg|gif)$/,
use: [
'file-loader'
]
}
提升image:Check out the image-webpack-loader and url-loader for more on how you can enhance your image loading process. 3) loading font:
{
test: /\.(woff|woff2|eot|ttf|otf)$/,
use: [
'file-loader'
]
}
在css中引入字体的时候要注意: @font-face { font-family: 'MyFont'; src: url('./font3.ttf') format('truetype'); // 不同格式的字体,format的值不一样,不一定跟文件后缀一致,如果写错,会出错,浏览器下载不到对应的字体文件 font-weight: 600; font-style: normal; }
src: url('./my-font.woff2') format('woff2'), url('./my-font.woff') format('woff');
4) loading data(json, csv, tsv, xml)
{
test: /\.(csv|tsv)$/,
use: [
'csv-loader'
]
},
{
test: /\.xml$/,
use: [
'xml-loader'
]
}
Output Management: 可以设置多个输入输出:
entry: {
app: './src/index.js',
print: './src/print.js'
},
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
},
1)每次都手动修改index.html引入bundle就不行了,可以用HtmlWebpackPlugin r来实现自动创建index.html. 同时html-webpack-template可以提供更多的特性。 npm i -D html-webpack-plugin
plugins: [
new HtmlWebpackPlugin({
title: 'Output Management'
})
],
2)清理/dist目录:clean-webpack-plugin npm i -D clean-webpack-plugin
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: 'Output Management'
})
],
Development: 1) using source maps:跟踪错误,指明具体的原文件,而不是打包后的文件。
devtool: 'inline-source-map', // 只在开发环境有用
2)development tool: webpack’s Watch mode: 监测文件的变化,自动编译,但并不会自动刷新浏览器
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"watch": "webpack --watch", // nom run watch
"build": "webpack"
},
webpack-dev-server: npm i -D webpack-dev-server
devServer: {
contentBase: './dist',
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"watch": "webpack --watch",
"start": "webpack-dev-server --open", // 启动服务器
"build": "webpack"
},
webpack-dev-middleware: npm i -D webpack-dev-middleware express
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
publicPath: '/'
},
Server.js
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"watch": "webpack --watch",
"start": "webpack-dev-server --open",
"server": "node server.js", // 启动服务器
"build": "webpack"
},
webpack-dev-server内部使用的就是webpack-dev-middleware
Hot Module Replacement, HMR(开发环境使用) 1)webpack-dev-server:
const webpack = require('webpack');
devServer: {
contentBase: './dist',
hot: true,
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: 'Development'
}),
new webpack.HotModuleReplacementPlugin()
],
只是这样子设置(只是设置了 devServer: { contentBase: './dist', }也一样),会每次完全重新刷新页面,重新拉取所有的资源。 加上
if (module.hot) {
module.hot.accept('./print.js', function() {
console.log('Accepting the updated printMe module!');
// printMe();
document.body.removeChild(element);
element = component();
document.body.appendChild(element);
})
}
当修改printMe的时候,会更新printMe绑定的函数,然后页面上的btn.onclick = printMe;也重新绑定新的printMe。但是会很麻烦(每个更新的文件都需要重新绑定),可以使用插件简化这个绑定的过程。
webpack输出真实的文件,而webpack-dev-server输出的文件只存在于内存中,不输出真实的文件
从外部角度看——自动刷新 当我们对业务代码做了一些修改然后保存后(command+s),页面会自动刷新,我们所做的修改会直接同步到页面上,而不需要我们刷新页面,或重新开启服务。从内部角度看——模块热替换 在热替换(HMR)机制里,不是重载整个页面,HMR程序会只加载被更新的那一部分模块,然后将其注入到运行中的APP中。
a. HMR with Stylesheets: style-loader:
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader',
'css-loader'
]
}
]
}
b. React Hot Loader: Tweak react components in real time. 2)webpack-dev-middleware: 使用webpack-hot-middleware
Code Splitting:将代码分割成多个bundles,实现按需加载或并行下载,优化加载速度。
optimization: {
splitChunks: {
chunks: 'all'
}
}
function getComponent() {
return import(/* webpackChunkName: "lodash_dan" */ 'lodash').then(({ default: _ }) => {
var element = document.createElement('div');
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
return element;
}).catch(error => 'An error occurred while loading the component');
}
getComponent().then(component => {
document.body.appendChild(component);
})
async function getComponent() {
var element = document.createElement('div');
const { default: _ } = await import(/* webpackChunkName: "lodash" */ 'lodash');
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
return element;
}
getComponent().then(component => {
document.body.appendChild(component);
});
Prefetching / Preloading modules
Bundle Analysis: 命令:webpack --profile --json > stats.json npm install -D webpack-bundle-analyzer https://github.com/webpack-contrib/webpack-bundle-analyzer 五彩斑斓的分析工具
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: 'Development'
}),
new webpack.HotModuleReplacementPlugin(),
new BundleAnalyzerPlugin({
generateStatsFile: true
})
],
Further Reading
b. require.ensure:
Lazy Loading(on demand) 需要的时候才去加载,加速了应用的初始化加载,可能有些模块永远不会加载减轻了大小。
button.onclick = e => import(/* webpackChunkName: "print" */ './print').then(module => {
var print = module.default;
print('sandy');
});
React: Code Splitting and Lazy Loading https://dzone.com/articles/lazy-loading-es2015-modules-in-the-browser
caching https://searchstorage.techtarget.com/definition/cache 1) output filenames output.filename: [name] [hash] [chunkhash] [contenthash] 注意点:a.[chunkhash] [contenthash]主要用于生产环境,不能和HMR同时使用(HMR用于开发环境)。区别?? [contenthash]改变js,hash值变化;改变js引入的css,hash值变化。不改变任何文件重新build,hash值不便 [chunkhash]改变js,hash值变化;改变js引入的css,hash值变化。不改变任何文件重新build,hash值不便 2)Extracting Boilerplate
optimization: {
runtimeChunk: 'single',
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'verdors',
chunks: 'all'
}
}
}
},
webpack provides an optimization feature to split runtime code into a separate chunk using the optimization.runtimeChunk option. Set it to single to create a single runtime bundle for all chunks:???
只是这样子cache,每次build之后公共模块的hash也会改变,所以要让公共模块不变。 A. 开发环境:NamedModulesPlugin,可以获得有用的输出,但耗时。 B. 生产环境:HashedModuleIdsPlugin
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: 'caching'
}),
new webpack.HashedModuleIdsPlugin()
],
Authoring Libraries 打包library
Environment Variables ???没看懂啥意思
Build Performance
Content Security Policies
Development-Vagrant 虚拟部署??
Dependency Management es6 modules commonjs amd
Installation
Scaffolding 脚手架???
Tree Shaking Import export 抖掉无用的代码
Production process.env.NODE_ENV在webpack config里面是undefined,在运行的脚本里可以获得development/production。
Production process.env.NODE_ENV在webpack config里面是undefined,在运行的脚本里可以获得development/production。例如,index.js:
console.log('index', process.env.NODE_ENV);
if (process.env.NODE_ENV !== 'production') {
console.log('looks like we are in development mode!')
}
将 webpack.config.js分成三个webpack.common.js webpack.dev.js webpack.prod.js webpack.common.js:
const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
app: './src/index.js'
},
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
title: 'Production'
})
],
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
webpack.dev.js:
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'development', // automatically configures DefinePlugin
devtool: 'inline-source-map', // strong source mapping
devServer: {
contentBase: './dist'
}
});
webpack.prod.js:
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'production', // loads TerserPlugin
devtool: 'source-map' // Avoid inline-*** and eval-*** use in production as they can increase bundle size and reduce the overall performance.
});
package.json:
"scripts": {
"start": "webpack-dev-server --open --config webpack.dev.js",
"build": "webpack --config webpack.prod.js"
},
shimming 使用全局变量的地方 或只在需要polyfill的浏览器按需加载对应的polyfill 使用ProvidePlugin插件,然后就可以全局使用_代替lodash了:
plugins: [
new webpack.ProvidePlugin({
_: 'lodash',
})
]
加载需要的polyfills:
entry: {
polyfills: './src/polyfills.js',
index: './src/index.js'
},
<script>
var modernBrowser = (
'fetch' in window &&
'assign' in Object
);
if ( !modernBrowser ) {
var scriptElement = document.createElement('script');
scriptElement.async = false;
scriptElement.src = '/polyfills.bundle.js';
document.head.appendChild(scriptElement);
}
</script>
学习部署工具webpack的使用: