Skip to content

Instantly share code, notes, and snippets.

@sunwu51
Created December 18, 2017 14:32
Show Gist options
  • Save sunwu51/65c8356f4d3116e69df9fa94bc073f9b to your computer and use it in GitHub Desktop.
Save sunwu51/65c8356f4d3116e69df9fa94bc073f9b to your computer and use it in GitHub Desktop.

Revisions

  1. sunwu51 created this gist Dec 18, 2017.
    282 changes: 282 additions & 0 deletions webpack.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,282 @@
    # Webpack 3.5.5
    ## 常用功能速查手册[截止2017/12/18]
    ### 1 基础配置
    ### 1.1 入口文件
    ```js
    //entry: {[entryChunkName: string]: string|Array<string>}
    //单入口: entry: './file.js'
    //多入口: entry: {app: './app.js',vendors: './vendors.js'}
    const config = {
    entry: {app: './app.js',vendors: './vendors.js'}
    };

    module.exports = config;
    ```
    ### 1.2 出口文件
    ```javascript
    //入口数决定了出口数

    //单入口如下
    const config = {
    entry: './file.js',
    output: {
    filename: 'bundle.js',
    path: '/home/proj/public/assets'
    }
    };
    //-------------------------------------------------------------
    //多入口如下
    {
    entry: {
    app: './app.js',
    search: './search.js'
    },
    output: {
    filename: '[name]-[chunkhash:6].js',
    path: __dirname + '/dist'
    }
    }

    // 写入到硬盘:./dist/app.js, ./dist/search.js
    ```
    ### 1.3 loader
    ```javascript
    //loader配置前需要先安装,例如react中用babel loader需要安装:
    //npm install --save-dev
    //babel-core babel-loader babel-preset-es2015 babel-preset-react
    const config={
    .........
    module: {
    loaders: [
    {
    test: /\.(js|jsx)$/,//匹配loaders处理文件正则表达式
    exclude: /node_modules/,//屏蔽不需要处理的文件
    loader: 'babel-loader?presets[]=es2015&presets[]=react'
    }
    ]
    }
    }
    ```
    ```
    //或者单独配置规则,根目录下.babelrc
    {
    "presets": [
    "react",
    "es2015"
    ]
    }
    ```
    有时候我们需要多个loader配置,如在js中import css文件需要css的loader
    ```
    npm install --save-dev style-loader css-loader
    ```
    ```javascript
    module: {
    rules: [
    {
    test: /\.(js|jsx)$/,
    exclude: /node_modules/,
    loader: 'babel?presets[]=es2015&presets[]=react'
    },
    {
    test: /\.css$/,
    use: [
    'style-loader',
    'css-loader'
    ]
    },
    ]
    }
    ```
    ### 1.4 构建目标
    默认为web即浏览器环境运行的js,可选值中node则代表nodejs环境运行的js,还有其他可选值不多介绍。
    ```javascript
    const conf={
    ...
    target:"web"
    }
    ```
    ### 1.5 插件
    插件直接引入,不需要写代码就会产生自己应有的作用
    ```javascript
    //这里添加一个webpack自带的uglifyjs插件,用于压缩js代码
    //然后添加一个HtmlWebpackPlugin是帮忙生成一个index.html文件,改文件里引入了所有output的js
    const webpack = require('webpack');
    const HTMLWebpackPlugin = require('html-webpack-plugin');
    const conf={
    ...
    plugins:[
    new webpack.optimize.UglifyJsPlugin({
    compress: {warnings: false}
    }),
    new HtmlWebpackPlugin()
    ]
    }
    ```

    ### 2 进阶主题
    ### 2.1 如何选择loader
    如果使用了ES6高级语法如import等,那你需要`babel`的加载器。

    如果使用了某种框架(如react)下的jsx语法,那你需要指定babel设置`presets[]=es2015&presets[]=react`

    如果在js中使用`import xx.css`方式引入css,那你需要`style-loader``css-loader`,会将改style放入head中。

    如果在js中使用import引入图片、字体等,那你需要`file-loader`,轻松将图或字体混入jsx style写法中。

    以上loader可以通过以下指令安装
    ```
    npm install --save-dev babel-core babel-loader babel-preset-es2015 babel-preset-react
    npm install --save-dev style-loader css-loader
    npm install --save-dev file-loader
    ```
    ### 2.2 如何实现代码分块
    在多入口的例子中已经实现每个页面的js各自导出,但若俩页面都引用jquery分别导出的两份js中都有jquery的封装,是一种带宽浪费。

    公共代码抽取----`CommonsChunkPlugin`
    ```javascript
    //利用webpack内部模块CommonsChunkPlugin,实现提取公共js单独输出
    //这里name属性指定的就是output中的[name],也可以直接指定filename属性
    plugins:[
    new webpack.optimize.CommonsChunkPlugin({
    name: 'common' // Specify the common bundle's name.
    })
    ]

    output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist')
    }
    ```
    [但是公共代码不代表就是一个库的代码,可能是俩库或者和自己util混合的]

    单独剥离第三方库----`CommonsChunkPlugin`
    ```javascript
    entry: {
    bundle: 'app'
    vendor: ['react']
    }

    plugins: [
    new webpack.optimize.CommonsChunkPlugin('vendor', 'vendor.js')
    ]
    //这里['react']能在入口的文件中识别其引入,并将其剥离
    //后面的‘vendor’是之前的键名,vendor.js是生成的文件名
    ```

    动态加载js---------`import`
    webpack.config.js
    ```javascript
    const HTMLWebpackPlugin = require('html-webpack-plugin');

    const config={
    entry:{
    index: './index.js',
    },
    output:{
    filename: "[name]-bundle.js",
    path: __dirname+'/dist'
    },
    plugins:[ new HTMLWebpackPlugin() ]
    }
    module.exports = config;
    ```
    index.js
    ```
    console.log("index")
    setTimeout(function(){
    import('./app').then(res=>{
    console.log(res.value)
    res.fun()
    })
    },3000)
    ```
    app.js
    ```
    export default {value:12345,fun:()=>{console.log('app')}}
    ```
    首先加载index.html+index.js,打印index。3s后加载0-bundle.js,打印12345 app。注意这里我们并没有让他输出0-bundle.js,webpack自动从代码中判断出import这个可能加载的项,按照name=0编译出js,等待加载的时机。

    这里的setTimeout是事件的一种,实际可以替换为按钮点击,路由跳转等。

    上面有个小问题,就是往往我们要用babel-loader加载js,但是一旦用了babel如果不在文件首部使用import就报错,解决方案:
    yarn add --dev babel-plugin-syntax-dynamic-import
    ```
    module: {
    loaders: [
    {
    test: /\.(js|jsx)$/,//匹配loaders处理文件正则表达式
    exclude: /node_modules/,//屏蔽不需要处理的文件
    use:
    [
    {
    loader: 'babel-loader',
    options:{
    presets:'es2015',
    plugins:['syntax-dynamic-import']
    }
    }
    ]
    }
    ]
    }
    ```

    ### 3 小结
    开发中常用的webpack.config.js可以这么写:
    ```
    const HTMLWebpackPlugin = require('html-webpack-plugin');
    const webpack =require('webpack')
    const config={
    entry:{
    index: './index.js',
    },
    output:{
    filename: "[name]-bundle.js",
    path: __dirname+'/dist'
    },
    plugins:[
    new webpack.optimize.UglifyJsPlugin({
    compress: {}
    }),
    new HTMLWebpackPlugin()
    ],
    module: {
    loaders: [
    {
    test: /\.(js|jsx)$/,//匹配loaders处理文件正则表达式
    exclude: /node_modules/,//屏蔽不需要处理的文件
    use: [{
    loader: 'babel-loader',
    options:{
    presets:'es2015',
    plugins:['syntax-dynamic-import']
    }
    }
    ]
    },
    {
    test: /\.css$/,
    use: [
    'style-loader',
    'css-loader'
    ]
    },
    ]
    }
    }
    module.exports = config;
    ```
    这之前需要安装到dev以下模块
    ```javascript
    babel-core
    babel-loader
    babel-preset-es2015
    //babel-preset-react
    style-loader css-loader
    html-webpack-plugin
    babel-plugin-syntax-dynamic-import
    ```