npm init
npm install -g webpack
npm install --save-dev webpack
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Webpack Sample Project</title>
</head>
<body>
<div id='root'>
</div>
<script src="bundle.js"></script>
</body>
</html>
var greeter = require('./Greeter.js');
document.getElementById('root').appendChild(greeter());
module.exports = function() {
var greet = document.createElement('div');
greet.textContent = "Hi there and greetings!";
return greet;
};
webpack {entry file/入口文件} {destination for bundled file/存放bundle.js的地方}
node_modules/.bin/webpack app/main.js public/bundle.js
进入项目目录
webpack app/main.js public/bundle.js
module.exports = {
entry: __dirname + "/app/main.js",//已多次提及的唯一入口文件
output: {
path: __dirname + "/public",//打包后的文件存放的地方
filename: "bundle.js"//打包后输出文件的文件名
}
}
注:“__dirname”是node.js中的一个全局变量,它指向当前执行脚本所在的目录。
webpack
"scripts": {
"start":"webpack"
}
注:package.json中的脚本部分已经默认在命令前添加了node_modules/.bin路径,所以无论是全局还是局部安装的Webpack,你都不需要写前面那指明详细的路径了。
npm的start是一个特殊的脚本名称,它的特殊性表现在,在命令行中使用npm start就可以执行相关命令,如果对应的此脚本名称不是start,想要在命令行中运行时,需要这样用npm run {script name}如npm run build
"scripts": {
"webpack":"webpack"
},
npm run webpack
devtool选项 | 配置结果 |
---|---|
source-map | 在一个单独的文件中产生一个完整且功能完全的文件。这个文件具有最好的source map,但是它会减慢打包文件的构建速度; |
cheap-module-source-map | 在一个单独的文件中生成一个不带列映射的map,不带列映射提高项目构建速度,但是也使得浏览器开发者工具只能对应到具体的行,不能对应到具体的列(符号),会对调试造成不便; |
eval-source-map | 使用eval打包源文件模块,在同一个文件中生成干净的完整的source map。这个选项可以在不影响构建速度的前提下生成完整的sourcemap,但是对打包后输出的JS文件的执行具有性能和安全的隐患。不过在开发阶段这是一个非常好的选项,但是在生产阶段一定不要用这个选项; |
cheap-module-eval-source-map | 这是在打包文件时最快的生成source map的方法,生成的Source Map 会和打包后的JavaScript文件同行显示,没有列映射,和eval-source-map选项具有相似的缺点; |
在学习阶段以及在小到中性的项目上,eval-source-map是一个很好的选项,不过记得只在开发阶段使用它,继续上面的例子,进行如下配置
devtool: 'eval-source-map',//配置生成Source Maps,选择合适的选项
npm install --save-dev webpack-dev-server
webpack-dev-server --open
启动了,默认8080端口 或者我们可以用配置文件来启动
devserver配置选项 | 功能描述 |
---|---|
contentBase | 默认webpack-dev-server会为根文件夹提供本地服务器,如果想为另外一个目录下的文件提供本地服务器,应该在这里设置其所在目录(本例设置到“public"目录) |
port | 设置默认监听端口,如果省略,默认为”8080“ |
compress | 是否使用Gzip |
inline | 设置为true,当源文件改变时会自动刷新页面 |
historyApiFallback | 在开发单页应用时非常有用,它依赖于HTML5 history API,如果设置为true,所有的跳转将指向index.html |
更多配置文件开发中 Server(DevServer)
devServer: {
contentBase: __dirname+"/public", //本地服务器所加载的页面所在的目录
compress: true, // 是否使用Gzip
port: 9000, // 指定端口 不指定端口默认为1080
historyApiFallback: true, //不跳转
inline: true //实时刷新
}
"scripts": {
"server": "webpack-dev-server"
},
使用不同的loader可以处理各种不同的文件
test | 一个匹配loaders所处理的文件的拓展名的正则表达式(必须) |
---|---|
loader | loader的名称(必须) |
include/exclude | 手动添加必须处理的文件(文件夹)或屏蔽不需要处理的文件(文件夹)(可选); |
query | 为loaders提供额外的设置选项(可选) |
npm install --save-dev json-loader
module: {//在配置文件里添加JSON loader
loaders: [
{
test: /\.json$/,
loader: "json"
}
]
},
{
"testText": "啦啦啦,我是JSON"
}
var testText = require('./jsontext.json'); //引入json
module.exports = function () {
var greet = document.createElement('div');
greet.textContent = testText.testText; // 使用
return greet;
};
不用介绍了吧 编译JavaScript的平台
先安装 嗯 一次性安装多个
npm install --save-dev babel-core babel-loader babel-preset-es2015 babel-preset-react
嗯 还得装react
npm install --save react react-dom
import React, {Component} from 'react'
import testText from './jsontext.json';
class Greeter extends Component{
render() {
return (
<div>
{testText.testText}
</div>
);
}
}
export default Greeter
import React from 'react';
import {render} from 'react-dom';
import Greeter from './Greeter';
render(<Greeter />, document.getElementById('root'));
虽然能在webpack.config.js配置,但是 那么多 真的好么。
{
"presets": ["react", "es2015"]
}
module: {//在配置文件里添加JSON loader
loaders: [
{
test: /\.json$/,
loader: "json-loader"
},
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader', //在webpack的module部分的loaders里进行配置即可
query: {
presets: ['es2015', 'react']
}
}
]
},
webpack提供两个工具处理样式表,css-loader 和 style-loader,二者处理的任务不同,css-loader使你能够使用类似@import 和 url(...)的方法实现 require()的功能,style-loader将所有的计算后的样式加入页面中,二者组合在一起使你能够把样式表嵌入webpack打包后的JS文件中。
npm install --save-dev style-loader css-loader
{
test: /\.css$/,
loader: [ 'style-loader', 'css-loader' ]//添加对样式表的处理
}
html{
background-color: red;
}
body{
font-size: 100px;
}
再去 主入口引入。。main.js 文件 前面说过
import './main.css';//使用require导入css文件
通常情况下,css会和js打包到同一个文件中,并不会打包为一个单独的css文件,不过通过合适的配置webpack也可以把css打包为单独的文件的 好处就是CSS模块,所有的类名,动画名默认都只作用于当前模块(不用费尽心机去起名了。。)😄
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: { modules: true }
}
]
}
.mod{
background-color: blue;
font-size: 20px;
}
import React, {Component} from 'react'
import testText from './jsontext.json';
import styles from './Greeter.css' // 引入css
class Greeter extends Component{
render() {
return (
<div className={styles.mod}> //使用
{testText.testText}
</div>
);
}
}
export default Greeter
类名变得只有他妈(webpack)才认识了 有兴趣可以去瞅瞅文档我是文档
** 常用的Less Loader、 Sass Loader、 Stylus Loader 还有个平台型处理器PostCSS 就用这个举例了**
老样子 先安装 顺便装上autoprefixer这个神器
npm install --save-dev postcss-loader autoprefixer
{
test: /\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: { modules: true, sourceMap: true }
},
'postcss-loader'
],
}
module.exports = {
plugins: [
require('autoprefixer')
]
}
display: flex;
"browserslist": [
"> 5%"
]
** 先说一波 Loaders和Plugins不是一个玩意的 loaders是在打包构建过程中用来处理源文件的(JSX,Scss,Less..),一次处理一个,插件并不直接操作单个文件,它直接对整个构建过程其作用。嗯 webpack的两根大腿
首先 用啥装啥。。233 ,然后 我用webpack。。。。 在配置文件最上面引入。。
var webpack = require('webpack');
然后 用BannerPlugin写点字 嗯 证明有效啊
plugins: [
new webpack.BannerPlugin("嘿嘿,生效了")//在这个数组中new一个就可以了
],
插件太多。。套路一样。就不演示了
UglifyJS plugins 是内置插件,用于代码压缩混淆 直接在插件配置那加上
new webpack.optimize.UglifyJsPlugin() // 代码混淆
OK 然后直接去配置文件的plugins配置,重新生成bundle文件 你会发现。。变量名变成a,b,c了。。。。
开发 测试 生产 需要的流程不一样,就需要多个配置文件了,比如生产环境用webpack.production.config.js这个配置 在package.json加入快捷启动方式
"build": "NODE_ENV=production webpack --config ./webpack.production.config.js --progress"
NODE_ENV是node的环境变量 一般根据它来切换一些配置 也可以通过
new webpack.DefinePlugin({
'process.env.environment': JSON.stringify(process.env.NODE_ENV)
}),
传给前端 对代码进行处理
通过指定webpack config文件的方式 也可以切换不同的配置文件逻辑
var path = require('path');
{
// 点击选项名称,获取文档详细
// 点击带箭头的项目,展示「更多示例 / 高级选项」
entry: "./app/entry", // string | object | array
// 这里应用程序开始执行
// webpack 开始打包
output: {
// webpack 如何输出结果的相关选项
path: path.resolve(__dirname, "dist"), // string
// 所有输出文件的目标路径
// 必须是绝对路径(使用 Node.js 的 path 模块)
filename: "bundle.js", // string
// 「入口分块(entry chunk)」的文件名模板(出口分块?)
publicPath: "/assets/", // string
// 输出解析文件的目录,url 相对于 HTML 页面
library: "MyLibrary", // string,
// 导出库(exported library)的名称
libraryTarget: "umd", // 通用模块定义
// 导出库(exported library)的类型
/* 高级输出配置(点击显示) */
},
module: {
// 关于模块配置
rules: [
// 模块规则(配置加载器、解析器等选项)
{
test: /\.jsx?$/,
include: [
path.resolve(__dirname, "app")
],
exclude: [
path.resolve(__dirname, "app/demo-files")
]
// 这里是匹配条件,每个选项都接收一个正则表达式或字符串
// test 和 include 具有相同的作用,都是必须匹配选项
// exclude 是必不匹配选项(优先于 test 和 include)
// 最佳实践:
// - 只在 test 和 文件名匹配 中使用正则表达式
// - 在 include 和 exclude 中使用绝对路径数组
// - 尽量避免 exclude,更倾向于使用 include
issuer: { test, include, exclude },
// issuer 条件(导入源)
enforce: "pre",
enforce: "post",
// 标识应用这些规则,即使规则覆盖(高级选项)
loader: "babel-loader",
// 应该应用的 loader,它相对上下文解析
// 为了更清晰,`-loader` 后缀在 webpack 2 中不再是可选的
// 查看 webpack 1 升级指南。
options: {
presets: ["es2015"]
},
// loader 的可选项
},
{
test: "\.html$"
use: [
// 应用多个 loader 和选项
"htmllint-loader",
{
loader: "html-loader",
options: {
/* ... */
}
}
]
},
{ oneOf: [ /* rules */ ] }
// 只使用这些嵌套规则之一
{ rules: [ /* rules */ ] }
// 使用所有这些嵌套规则(合并可用条件)
{ resource: { and: [ /* 条件 */ ] } }
// 仅当所有条件都匹配时才匹配
{ resource: { or: [ /* 条件 */ ] } }
{ resource: [ /* 条件 */ ] }
// 任意条件匹配时匹配(默认为数组)
{ resource: { not: /* 条件 */ } }
// 条件不匹配时匹配
],
/* 高级模块配置(点击展示) */
},
resolve: {
// 解析模块请求的选项
// (不适用于对加载器(loader)解析)
modules: [
"node_modules",
path.resolve(__dirname, "app")
],
// 用于查找模块的目录
extensions: [".js", ".json", ".jsx", ".css"],
// 使用的扩展名
alias: {
// 模块别名列表
"module": "new-module",
// 起别名:"module" -> "new-module" 和 "module/path/file" -> "new-module/path/file"
"only-module$": "new-module",
// 起别名 "only-module" -> "new-module",但不匹配 "module/path/file" -> "new-module/path/file"
"module": path.resolve(__dirname, "app/third/module.js"),
// 起别名 "module" -> "./app/third/module.js" 和 "module/file" 会导致错误
// 模块别名相对于当前上下文导入
},
/* 可供选择的别名语法(点击展示) */
/* 高级解析选项(点击展示) */
},
performance: {
hints: "warning", // 枚举
maxAssetSize: 200000, // 整数类型(以字节为单位)
maxEntrypointSize: 400000, // 整数类型(以字节为单位)
assetFilter: function(assetFilename) {
// 提供资源文件名的断言函数
return assetFilename.endsWith('.css') || assetFilename.endsWith('.js');
}
},
devtool: "source-map", // enum
// 通过在浏览器调试工具(browser devtools)中添加元信息(meta info)增强调试
// 牺牲了构建速度的 `source-map' 是最详细的。
context: __dirname, // string(绝对路径!)
// webpack 的主目录
// entry 和 module.rules.loader 选项
// 相对于此目录解析
target: "web", // 枚举
// 包(bundle)应该运行的环境
// 更改 块加载行为(chunk loading behavior) 和 可用模块(available module)
externals: ["react", /^@angular\//],
// 不要遵循/打包这些模块,而是在运行时从环境中请求他们
stats: {
/* TODO */
},
devServer: {
/* TODO */
},
plugins: [
// ...
],
// 附加插件列表
/* 高级配置(点击展示) */
resolveLoader: { /* 等同于 resolve */ }
// 独立解析选项的 loader
profile: true, // boolean
// 捕获时机信息
bail: true, //boolean
// 在第一个错误出错时抛出,而不是无视错误。
cache: false, // boolean
// 禁用/启用缓存
watch: true, // boolean
// 启用观察
watchOptions: {
aggregateTimeout: 1000, // in ms
// 将多个更改聚合到单个重构建(rebuild)
poll: true,
poll: 500, // 间隔单位 ms
// 启用轮询观察模式
// 必须用在不通知更改的文件系统中
// 即 nfs shares(译者注:Network FileSystem,最大的功能就是可以透過網路,讓不同的機器、不同的作業系統、可以彼此分享個別的檔案 ( share file ))
},
node: {
/* TODO */
},
recordsPath: path.resolve(__dirname, "build/records.json"),
recordsInputPath: path.resolve(__dirname, "build/records.json"),
recordsOutputPath: path.resolve(__dirname, "build/records.json"),
// TODO
}