webpack学习笔记

学习笔记

四个核心概念:入口(entry)、输出(output)、loader、插件(plugins)

1、在项目中安装webpack:在根目录下打开命令窗口,输入 npm install webpack --save-dev 安装webpack。

2、在js文件中引入另外一个js文件,如:在根目录下的 hello.js 中引入根目录下的 world.js

 require('./world.js');

3、webpack 打包文件命令webpack 要打包的文件 打包后的文件
如:webpack hello.js hello.bundle.js

4、在js中引入css文件
webpack本身是不支持 .css 格式的,需要使用loader插件
npm install css-loader style-loader --save-dev
css-loader:使webpack能处理 .css 文件
style-loader:将css-loader处理过的css用style标签包裹起来插入到HTML里面
有以下两种方式:
(1)require(‘style-loader!css-loader!./style.css’) // 插件通过 ! 连接
(2)require(’./style.css’)
打包命令为:webpack hello.js hello.bundle.js --module-bind 'css=style-loader!css-loader'
如果要实现内容改变自动打包则:webpack hello.js hello.bundle.js --module-bind 'css=style-loader!css-loader' --watch

5、通过命令创建文件夹mkdir 文件夹名称

6、使用webpack命令的话,webpack会默认使用根目录下的webpack.config.js,将其作为默认的配置。
也可通过 --config 来使用其他配置文件,例如:webpack --config webpack.dev.config.js

7、commenJS的模块化输出module.exports = {}

8、wenpack.config.js配置文件
entry:打包入口从哪个文件开始
output:打包以后的文件放在哪,并且定义打包以后的文件名
最基本的配置:

module.exports = {
	entry: './src/script/main.js',
	output: {
		path: './dist/js',
		filename: 'bundle.js',
	},
}

9、在 package.json 中配置 webpack 命令
"scripts": {...}, 中添加如下:

"webpack": "webpack --config webpack.config.js --progress --display-module --colors --display-reason",

然后在命令窗口输入:npm run webpack
--progress:看到打包的过程
--display-module:查看打包的模块
--colors:打包时出来的字是彩色的
--display-reason:查看打包的原因

10、entry:有三种输入方式
(1)entry: './src/script/main.js',
(2)entry: ['./entry1', './entry2'] // 两个平行的不相依赖的文件打包到一起
(3)用于多页面应用

{
	entry: {
		page1: './page1',
		page2: ['./entry1', './entry2']
	},
	output: {
		fillname: '[name].bundle.js', // [name]-[hash].js  [name]-[chunkhash].js 
		chunkFilename: '[id].bundle.js'
	}
}

11、webpack插件:html-webpack-plugin
安装命令:npm install html-webpack-plugin --save-dev

  • (1)在webpac.config.js文件中引用:
var htmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
	...
	plugins:[
		new htmlWebpackPlugin({
			template: 'index.html'
		})
	]
}
  • (2)html-webpack-plugin的参数:
filename: 'index-[hash].html', // 指定生成的文件名称,一般直接使用 index.html
template: 'index.html', // 模板
inject: 'head', // 指定生成的脚本放在的位置,放在head标签中还是会放在body标签中
minify:{ // 压缩html文件
	removeComments: true, // 删除注释
	collapseWhitespace: true, // 删除空格
}
  • (3)通过在插件中传参,然后在模板中引用。
    webpack.config.js
var htmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
	...
	plugins:[
		new htmlWebpackPlugin({
			filename: 'index-[hash].html',
			template: 'index.html',
			inject: 'head',
			title: 'webpack is good',
			date: new Date()
		})
	]
}

在index.html中引用(类似模板引擎):

<title><%= htmlWebpackPlugin.options.title %></title>
<div> <%= htmlWebpackPlugin.options.date %> </div>
<div>
	<% for(var key in htmlWebpackPlugin){ %>
		<%= key %>
	<% } %>
</div>
<div>
<% for(var key in htmlWebpackPlugin.file){ %>
	<%= key %>:<%= JSON.stringify(htmlWebpackPlugin.file[key]) %>
<% } %>

<% for(var key in htmlWebpackPlugin.options){ %>
	<%= key %>:<%= JSON.stringify(htmlWebpackPlugin.options[key]) %>
<% } %>
</div>

12、设置打包上线后的地址,设置 output 的 publicPath 属性

module.exports = {
	...
	output: {
		path: './dist',
		filename: 'js/[name]-[chunkhash].js',
		publicPath: '', // 如设为:http://cdn.com/
	},
	...
}

publicPath:在 html 中引用的 js 的路径会替换为绝对地址以 publicPath 设置的值开头的路径。

13、使用 html-webpack-plugin 生成多页面html

var htmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
	entry: {
		main: './src/script/main.js',
		a: './src/script/a.js',
		b: './src/script/b.js',
		c: './src/script/c.js',
	},
	output: {
		path: './dist',
		filename: 'js/[name]-[chunkhash].js',
		publicPath: '', // 如设为:http://cdn.com/
	},
	plugins:[
		new htmlWebpackPlugin({
			filename: 'a.html',
			template: 'index.html',
			inject: 'body',
			title: 'this is a',
			chunks: ['main', 'a'], // 指向entry中的key,表示引用main.js和a.js
			excludeChunks: ['b','c'] // 表示引用除了b.js和c.js之外的js
		}),
		new htmlWebpackPlugin({
			filename: 'b.html',
			template: 'index.html',
			inject: 'body',
			title: 'this is b',
			chunks: ['b']
		}),
		new htmlWebpackPlugin({
			filename: 'c.html',
			template: 'index.html',
			inject: 'body',
			title: 'this is c',
			chunks: ['main', 'c']
		})
	]
}

14、优化:将 js 直接插入到 html 页面,而不是引用 js 文件,这样可以减少 http 请求

  • 在 head 标签中直接插入main.js中的代码:
<script type="text/javascript">
	<% compilation.assets[htmlWebpackPlugin.files.chunks.main.entry.substr(htmlWebpackPlugin.files.publicPath.length)].source() %>
</script>
  • 在 body 中:
<% for(var k in htmlWebpackPlugin.files.chunks){ %>
	<% if(k !== 'main'){ %>
		<script type="text/javascript" src="<%= htmlWebpackPlugin.files.chunks[k].entry %>"></script>
	<% } %>
<% } %>

15、loader

var htmlWebpackPlugin = require('html-webpack-plugin');
var path = require('path'); // nodejs中的path

module.exports = {
	entry: ...',
	output: {...},
	module: {
		loaders: [{
			test: /\.js$/, 
			loader: 'babel', // npm 安装:npm install --save-dev babel-loader babel-core
			exclude: './node_modules/',
			include: './src/',
			query: {
				presets: ['latest'] // 安装:npm install --save-dev babel-preset-latest
				// 也可以在 package.json 进行配置,即与script并列的添加属性:"babel":{"presets":["latest"]}
			}
		},{
			test: /\.js$/, 
			loader: 'babel', // npm 安装:npm install --save-dev babel-loader babel-core
			// exclude: './node_modules/',
			exclude: path.resolve(__dirname, 'node_modules'),
			// include: './src/',
			include: path.resolve(__dirname, 'src'),
			query: {
				presets: ['latest'] // 安装:npm install --save-dev babel-preset-latest
				// 也可以在 package.json 进行配置,即与script并列的添加属性:"babel":{"presets":["latest"]}
			}
		},{
			test: /\.html$/,
			loader: 'html-loader',
		},{
			test: /\.ejs$/, // 也可将文件后缀改为tpl
			loader: 'ejs-loader',
		},{
			test: /\.css$/,
			loader: 'style-loader!css-loader?importLoaders=1!postcss-loader',
		},{
			test: /\.less$/,
			loader: 'style!css!postcss!less',
		},{
			test: /\.scss$/,
			loader: 'style!css!postcss!sass',
		},{
			test: /\.(png|jpg|gif|svg))$/i,
			// loader: 'file-loader',
			loader: 'url-loader?limit=1000&name=assets/[name-[hash:5].[ext]',
			/* query: { // 指定图片打包路径
				name: 'assets/[name]-[hashs].[ext]'
			} */
		}],
	},
	postcss: [
		require('autoprefixer')({
			broswers: ['last 5 versions']
		})
	],
	...
}

16、使用绝对路径

var path = require('path'); // nodejs中的path
path.resolve(__dirname, 'app/src'); // 生成绝对路径,

resolve:解析,
__dirname:运行环境下的变量即当前环境下的路径
'app/src':相对路径
17、处理项目中的css

  • (1)postcss 安装:npm install postcss-loader --save-dev
module.exports = {
	...
	module: {
		loaders: [{
			test: /\.css$/,
			loader: 'style-loader!css-loader?importLoaders=1!postcss-loader',
			// loaders: ['style-loader','css-loader','postcss-loader']
		}],
	},
	post: [
		require('autoprefixer')({ // 为css样式加上浏览器前缀
			broswers: ['last 5 versions']
		})
	],
	...
}

?importLoaders=1:为传参,使css文件中通过 @import 引入的css也能被loader插件处理
loader的处理顺序是从右到左。

  • (2)less-loader
    安装: npm i less-loader --save-dev

18、在模板中使用相对路径的图片

<img src="${ require('../../assets/bg.png') }" />

webpack.config.js

const path = require('path');

module.exports = {
    mode: "production", // "production" | "development" | "none"

    entry: "./app/entry", // string | object | array
    /* entry: ["./app/entry1", "./app/entry2"],
    entry: {
        a: "./app/entry-a",
        b: ["./app/entry-b1", "./app/entry-b2"]
    }, */

    // webpack 如何输出结果的相关选项
    output: {
        // 所有输出文件的目标路径
        path: path.resolve(__dirname, "dist"), // 必须是绝对路径(使用 Node.js 的 path 模块)

        // 「入口分块(entry chunk)」的文件名模板(出口分块?)
        filename: 'bundle.js',
        /* filename: '[name].js', // 用于多个入口点(entry point)(出口点?)
        filename: '[chunkhash].js', // 用于长效缓存 */

        // 输出解析文件的目录,url 相对于 HTML 页面
        publicPath: "/assets/", // string
        /* publicPath: "",
        publicPath: "https://cdn.example.com/", */

        // 导出库(exported library)的名称
        library: "MyLibrary", // string,

        // 导出库(exported library)的类型
        libraryTarget: "umd2", // 通用模块定义
        libraryTarget: "commonjs2", // exported with module.exports
        libraryTarget: "commonjs-module", // 使用 module.exports 导出
        libraryTarget: "commonjs", // 作为 exports 的属性导出
        libraryTarget: "amd", // 使用 AMD 定义方法来定义
        libraryTarget: "this", // 在 this 上设置属性
        libraryTarget: "var", // 变量定义于根作用域下
        libraryTarget: "assign", // 盲分配(blind assignment)
        libraryTarget: "window", // 在 window 对象上设置属性
        libraryTarget: "global", // property set to global object
        libraryTarget: "jsonp", // jsonp wrapper


        // 在生成代码时,引入相关的模块、导出、请求等有帮助的路径信息。
        pathinfo: true, // boolean

        // 「附加分块(additional chunk)」的文件名模板
        chunkFilename: "[id].js",
        // chunkFilename: "[chunkhash].js", // 长效缓存(/guides/caching)
    
        // 用于加载分块的 JSONP 函数名
        jsonpFunction: "myWebpackJsonp", // string

        // 「source map 位置」的文件名模板
        sourceMapFilename: "[file].map", // string
        // sourceMapFilename: "sourcemaps/[file].map", // string
    
        // 「devtool 中模块」的文件名模板
        devtoolModuleFilenameTemplate: "webpack:///[resource-path]", // string
    
        // 「devtool 中模块」的文件名模板(用于冲突)
        devtoolFallbackModuleFilenameTemplate: "webpack:///[resource-path]?[hash]", // string
    
        // 在 UMD 库中使用命名的 AMD 模块
        umdNamedDefine: true, // boolean
    
        // 指定运行时如何发出跨域请求问题
        crossOriginLoading: "use-credentials", // 枚举
        // crossOriginLoading: "anonymous",
        // crossOriginLoading: false,
    },
    // 关于模块配置
    module: {
        // 模块规则(配置 loader、解析器等选项)
        rules: [
            // test 和 include 具有相同的作用,都是必须匹配选项
            // exclude 是必不匹配选项(优先于 test 和 include)
            {
                test: /\.jsx?$/,
                include: [
                    path.resolve(__dirname, "app")
                ],
                exclude: [
                    path.resolve(__dirname, "app/demo-files")
                ],
                // 最佳实践:
                // - 只在 test 和 文件名匹配 中使用正则表达式
                // - 在 include 和 exclude 中使用绝对路径数组
                // - 尽量避免 exclude,更倾向于使用 include

                // issuer 条件(导入源)
                issuer: { test, include, exclude },

                // 标识应用这些规则,即使规则覆盖(高级选项)
                enforce: "pre",
                // enforce: "post",

                // 应该应用的 loader,它相对上下文解析
                loader: "babel-loader",

                // loader 的可选项
                options: {
                    presets: ["es2015"]
                },
            },{
                test: /\.html$/,
                // test: "\.html$"

                use: [
                  // 应用多个 loader 和选项
                  "htmllint-loader",
                  {
                    loader: "html-loader",
                    options: {
                      /* ... */
                    }
                  }
                ]
            },
            // 只使用这些嵌套规则之一
            { oneOf: [ /* rules */ ] },
      
            // 使用所有这些嵌套规则(合并可用条件)
            { rules: [ /* rules */ ] },
      
            // 仅当所有条件都匹配时才匹配
            { resource: { and: [ /* 条件 */ ] } },
      
            // 任意条件匹配时匹配(默认为数组)
            { resource: { or: [ /* 条件 */ ] } },
            { resource: [ /* 条件 */ ] },
      
            // 条件不匹配时匹配
            { resource: { not: /* 条件 */ } }
        ],
        noParse: [
          /special-library\.js$/
        ],
        // 不解析这里的模块

        unknownContextRequest: ".",
        unknownContextRecursive: true,
        unknownContextRegExp: /^\.\/.*$/,
        unknownContextCritical: true,
        exprContextRequest: ".",
        exprContextRegExp: /^\.\/.*$/,
        exprContextRecursive: true,
        exprContextCritical: true,
        wrappedContextRegExp: /.*/,
        wrappedContextRecursive: true,
        wrappedContextCritical: false,
        // specifies default behavior for dynamic requests
    },
    // 解析模块请求的选项
    // (不适用于对 loader 解析)
    resolve: {
        // 用于查找模块的目录
        modules: [
          "node_modules",
          path.resolve(__dirname, "app")
        ],
        // 使用的扩展名
        extensions: [".js", ".json", ".jsx", ".css"],
        // 模块别名列表
        alias: {      
            // 起别名:"module" -> "new-module" 和 "module/path/file" -> "new-module/path/file"
            "module": "new-module",

            // 起别名 "only-module" -> "new-module",但不匹配 "only-module/path/file" -> "new-module/path/file"
            "only-module$": "new-module",

            // 起别名 "module" -> "./app/third/module.js" 和 "module/file" 会导致错误
            "module": path.resolve(__dirname, "app/third/module.js"),
            // 模块别名相对于当前上下文导入
        },
        /* 可供选择的别名语法(点击展示) */
        alias: [
            {
                name: "module", // 旧的请求
                alias: "new-module", // 新的请求
                onlyModule: true // 如果为 true,只有 "module" 是别名,如果为 false,"module/inner/path" 也是别名 
            }
        ],
    },
    performance: {
        hints: "warning", // 枚举
        // hints: "error", // 性能提示中抛出错误
        // hints: false, // 关闭性能提示
        maxAssetSize: 200000, // 整数类型(以字节为单位)
        maxEntrypointSize: 400000, // 整数类型(以字节为单位)
        assetFilter: function(assetFilename) {
          // 提供资源文件名的断言函数
          return assetFilename.endsWith('.css') || assetFilename.endsWith('.js');
        }
    },

    // 通过在浏览器调试工具(browser devtools)中添加元信息(meta info)增强调试
    // 牺牲了构建速度的 `source-map' 是最详细的。
    devtool: "source-map", // enum
    // devtool: "inline-source-map", // 嵌入到源文件中
    // devtool: "eval-source-map", // 将 SourceMap 嵌入到每个模块中
    // devtool: "hidden-source-map", // SourceMap 不在源文件中引用
    // devtool: "cheap-source-map", // 没有模块映射(module mappings)的 SourceMap 低级变体(cheap-variant)
    // devtool: "cheap-module-source-map", // 有模块映射(module mappings)的 SourceMap 低级变体
    // devtool: "eval", // 没有模块映射,而是命名模块。以牺牲细节达到最快。
     
    // webpack 的主目录,entry 和 module.rules.loader 选项相对于此目录解析
    context: __dirname, // string(绝对路径!)

    // 包(bundle)应该运行的环境
    // 更改 块加载行为(chunk loading behavior) 和 可用模块(available module)
    target: "web", // 枚举
    // target: "webworker", // WebWorker
    // target: "node", // node.js 通过 require
    // target: "async-node", // Node.js 通过 fs and vm
    // target: "node-webkit", // nw.js
    // target: "electron-main", // electron,主进程(main process)
    // target: "electron-renderer", // electron,渲染进程(renderer process)
    // target: (compiler) => { /* ... */ }, // 自定义

    // 不要遵循/打包这些模块,而是在运行时从环境中请求他们
    externals: ["react", /^@angular\//],
    /* 
    externals: "react", // string(精确匹配)
    externals: /^[a-z\-]+($|\/)/, // 正则
    externals: { // 对象
        angular: "this angular", // this["angular"]
        react: { // UMD
            commonjs: "react",
            commonjs2: "react",
            amd: "react",
            root: "React"
        }
    },
    externals: (request) => { /* ... */ return "commonjs " + request }
    */

    // 精确控制要显示的 bundle 信息
    stats: "errors-only",
    /*
    stats: { //object
        assets: true,
        colors: true,
        errors: true,
        errorDetails: true,
        hash: true,
        // ...
    },
    */

    devServer: {
        proxy: { // proxy URLs to backend development server
          '/api': 'http://localhost:3000'
        },
        contentBase: path.join(__dirname, 'public'), // boolean | string | array, static file location
        compress: true, // enable gzip compression
        historyApiFallback: true, // true for index.html upon 404, object for multiple paths
        hot: true, // hot module replacement. Depends on HotModuleReplacementPlugin
        https: false, // true for self-signed, object for cert authority
        noInfo: true, // only errors & warns on hot reload
        // ...
    },

    // 附加插件列表
    plugins: [
        // ...
    ],


/*** 高级配置 ***/
    // 独立解析选项的 loader
    resolveLoader: { /* 等同于 resolve */ }

    // 限制并行处理模块的数量
    parallelism: 1, // number

    // 捕获时机信息
    profile: true, // boolean

    // 在第一个错误出错时抛出,而不是无视错误。
    bail: true, //boolean

    // 禁用/启用缓存
    cache: false, // boolean

    // 启用观察
    watch: true, // boolean

    watchOptions: {
        // 将多个更改聚合到单个重构建(rebuild)
        aggregateTimeout: 1000, // in ms
        poll: true,
        poll: 500, // 间隔单位 ms
        // 启用轮询观察模式
        // 必须用在不通知更改的文件系统中
        // 即 nfs shares(译者注:Network FileSystem,最大的功能就是可以透過網路,讓不同的機器、不同的作業系統、可以彼此分享個別的檔案 ( share file ))
    },

    // Polyfills and mocks to run Node.js-environment code in non-Node environments. 
    node: {
        console: false, // boolean | "mock"
        global: true, // boolean | "mock"
        process: true, // boolean
        __filename: "mock", // boolean | "mock"
        __dirname: "mock", // boolean | "mock"
        Buffer: true, // boolean | "mock"
        setImmediate: true // boolean | "mock" | "empty"
    },

    recordsPath: path.resolve(__dirname, "build/records.json"),
    recordsInputPath: path.resolve(__dirname, "build/records.json"),
    recordsOutputPath: path.resolve(__dirname, "build/records.json"),
    // TODO
};
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值