Razzle: рд╕реАрдПрд╕рдПрд╕ рдореЙрдбреНрдпреВрд▓ рдХреЗ рд╕рд╛рде рд░реИрдЬрд╝рд▓ рдПрд╕рд╕реАрдПрд╕рдПрд╕

рдХреЛ рдирд┐рд░реНрдорд┐рдд 26 рдордИ 2018  ┬╖  4рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ  ┬╖  рд╕реНрд░реЛрдд: jaredpalmer/razzle

рдореИрдВ рдПрд╕рд╕реАрдПрд╕рдПрд╕ рдХреЗ рд╕рд╛рде рд╕реАрдПрд╕рдПрд╕ рдореЙрдбреНрдпреВрд▓ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣рд╛ рд╣реВрдВред

рдореИрдВ рдЗрд╕реЗ рдПрд╕рд╕реАрдПрд╕рдПрд╕ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореЙрдбреНрдпреВрд▓ рдореЗрдВ рд▓рд╛рдиреЗ рдХрд╛ рдкреНрд░рдмрдВрдзрди рдХрд░рддрд╛ рд╣реВрдВред рд╣рд╛рд▓рд╛рдВрдХрд┐, рдореИрдВ рдПрд╕рд╕реАрдПрд╕рдПрд╕ рдХреЗ рд╕рд╛рдорд╛рдиреНрдп рдЖрдпрд╛рдд рдирд╣реАрдВ рдХрд░ рд╕рдХрддрд╛, рдореИрдВрдиреЗ рдХрдИ рдирд┐рдпрдореЛрдВ рдХреЛ рдЖрдЧреЗ рдмрдврд╝рд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХреА рд╣реИ, рдФрд░ рдореЙрдбреНрдпреВрд▓.рдПрд╕рд╕реАрдПрд╕рдПрд╕ рдХреЛ рдЫреЛрдбрд╝рдХрд░ рд▓реЗрдХрд┐рди рдпрд╣ рдХрд╛рдо рдирд╣реАрдВ рдХрд░рддрд╛ рд╣реИред рдЕрдЪреНрдЫрд╛ рд╣реЛрдЧрд╛ рдЕрдЧрд░ рдпрд╣рд╛рдВ рдХреЛрдИ рдореБрдЭреЗ рдЗрд╕рдореЗрдВ рд╣рд╛рде рджреЗ рд╕рдХреЗред

рдореЙрдбреНрдпреВрд▓ рдХреЗ рд╕рд╛рде рдХреЗрд╡рд▓ рдПрд╕рд╕реАрдПрд╕рдПрд╕ рдХреЗ рд▓рд┐рдП рдпрд╣ рдореЗрд░реА рд╡рд░реНрддрдорд╛рди рдХрд╛рдордХрд╛рдЬреА рдХреЙрдиреНрдлрд╝рд┐рдЧрд░реЗрд╢рди рд╣реИ, рд▓реЗрдХрд┐рди рд╕рд╛рдорд╛рдиреНрдп рдЖрдпрд╛рддред

рдзрдиреНрдпрд╡рд╛рджред

'use strict';

const autoprefixer = require('autoprefixer');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const path = require('path');

const scssPlugin = new ExtractTextPlugin(
  'static/css/[name].[hash:8].css'
);

module.exports = {
  modify: (baseConfig, { target, dev }, webpack) => {
    const appConfig = Object.assign({}, baseConfig);

    appConfig.resolve.modules.push('src', 'node_modules');

    // Setup SCSS
    if (target === 'web') {
      appConfig.module.rules.push(
        dev
        ? {
          test: /\.scss$/,
          use: [
            'style-loader',
            {
              loader: 'css-loader',
              options: {
                modules: true,
                sourceMap: true,
                localIdentName: '[local]__[hash:base64:5]'
              },
            },
            {
              loader: 'postcss-loader',
              options: {
                ident: 'postcss', // https://webpack.js.org/guides/migrating/#complex-options
                plugins: () => [
                  autoprefixer({
                      browsers: [
                        '>1%',
                        'last 4 versions',
                        'Firefox ESR',
                        'not ie < 9', // React doesn't support IE8 anyway
                        ],
                  }),
                    ],
              },
            },
            'sass-loader',
              ],
        }
        : {
          test: /\.scss$/,
          use: scssPlugin.extract({
              fallback: 'style-loader',
              use: [
                {
                  loader: 'css-loader',
                  options: {
                    modules: true,
                    minimize: true,
                    importLoaders: 1,
                    localIdentName: '[hash:base64:5]'
                  },
                },
              {
                loader: 'postcss-loader',
                options: {
                  ident: 'postcss', // https://webpack.js.org/guides/migrating/#complex-options
                  plugins: () => [
                    autoprefixer({
                        browsers: [
                          '>1%',
                          'last 4 versions',
                          'Firefox ESR',
                          'not ie < 9', // React doesn't support IE8 anyway
                          ],
                    }),
                      ],
                },
              },
                'sass-loader',
                ],
          }),
        }
      );


    } else {
      // On the server, we can just simply use css-loader to
      // deal with scss imports
      appConfig.module.rules.push(
        dev ? {
          test: /\.scss$/,
          use: scssPlugin.extract({
              fallback: 'style-loader',
              use: [
                {
                  loader: 'css-loader',
                  options: {
                    modules: true,
                    minimize: true,
                    importLoaders: 1,
                    localIdentName: '[local]__[hash:base64:5]'
                  },
                },
              {
                loader: 'postcss-loader',
                options: {
                  ident: 'postcss', // https://webpack.js.org/guides/migrating/#complex-options
                  plugins: () => [
                    autoprefixer({
                        browsers: [
                          '>1%',
                          'last 4 versions',
                          'Firefox ESR',
                          'not ie < 9', // React doesn't support IE8 anyway
                    ],
                    }),
                ],
                },
              },
                'sass-loader',
          ],
          })
        }
        : {
          test: /\.scss$/,
          use: scssPlugin.extract({
              fallback: 'style-loader',
              use: [
                {
                  loader: 'css-loader',
                  options: {
                    modules: true,
                    minimize: true,
                    importLoaders: 1,
                    localIdentName: '[hash:base64:5]'
                  },
                },
              {
                loader: 'postcss-loader',
                options: {
                  ident: 'postcss', // https://webpack.js.org/guides/migrating/#complex-options
                  plugins: () => [
                    autoprefixer({
                        browsers: [
                          '>1%',
                          'last 4 versions',
                          'Firefox ESR',
                          'not ie < 9', // React doesn't support IE8 anyway
                        ],
                    }),
                    ],
                },
              },
                'sass-loader',
              ],
          }
          ),
      });
    }


  appConfig.plugins.push(scssPlugin);

  return appConfig;
  },
};

рд╕рдмрд╕реЗ рдЙрдкрдпреЛрдЧреА рдЯрд┐рдкреНрдкрдгреА

рдЗрд╕рдХреЗ рд▓рд┐рдП рдереЛрдбрд╝рд╛ рджреЗрд░ рд╣реЛ рдЪреБрдХреА рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣рд╛рдВ рдореЗрд░реЗ рд▓рд┐рдП рдХреНрдпрд╛ рдХрд╛рдо рдХрд┐рдпрд╛ рд╣реИ:

const path = require("path");

module.exports = {
    modify(config, { target, dev }, webpack) {
        for (const rule of config.module.rules) {
            if (rule.test && rule.test.toString() === "/\\.module\\.css$/") {
                const scss = { ...rule };

                scss.test = /\.scss$/;
                scss.include = path.join(__dirname, "src");
                scss.use.push({ loader: "sass-loader" });

                config.module.rules.push(scss);

                break;
            }
        }

        return config;
    }
};

рд╕рднреА 4 рдЯрд┐рдкреНрдкрдгрд┐рдпрд╛рдБ

рдкрд░ рдПрдХ рдирдЬрд╝рд░ рдбрд╛рд▓реЗрдВ
https://github.com/natanelia/razzle-afterjs-redux-rnw-example
рдЙрд╕ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдЖрдлреНрдЯрд░ рд░реИрдЬрд╝рд▓ рдХреЗ рдкрд┐рдЫрд▓реЗ рд╕рдВрд╕реНрдХрд░рдг рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд░рд╣рд╛ рд╣реИ (рдЬреЛ рд╡реЗрдмрдкреИрдХ 3 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддрд╛ рд╣реИ), рд▓реЗрдХрд┐рди рдПрд╕рдПрдПрд╕ рд╕рдВрдмрдВрдзрд┐рдд рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдХрд╛рдо рдХрд░рддреА рд╣реИрдВред рдЖрдкрдХреЛ ExtractTextPlugin рдХреЛ рд╣рдЯрд╛рдирд╛ рд╣реЛрдЧрд╛ рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ webpack4 рдХрд╛ рд╕рдорд░реНрдерди рдирд╣реАрдВ рдХрд░ рд░рд╣рд╛ рд╣реИ (рдЬрд┐рд╕ рдкрд░ рдирдпрд╛ рд░реИрдЬрд╝рд▓ рдирд┐рд░реНрднрд░ рдХрд░рддрд╛ рд╣реИ)ред

рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдпрджрд┐ рдЖрдк рдЙрд╕ рдЙрджрд╛рд╣рд░рдг (рд╡реЗрдмрдкреИрдХ 4 рдХреЗ рд▓рд┐рдП) рдХреЗ рдореЗрд░реЗ рдЕрдкрдбреЗрдЯ рдкрд░ рд▓реВрдЯ рд▓реЗрдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рддреЛ рдиреАрдЪреЗ рдПрдХ рд▓реВрдЯ рд▓реЗрдВ:

const path = require('path');
const resolve=path.resolve;

const autoprefixer = require('autoprefixer');
const fs=require('fs'); 

//var treeify = require('treeify');

const { BundleAnalyzerPlugin } = require( "webpack-bundle-analyzer" );
const paths= require ('razzle/config/paths');

//does not yet work with webpack4
//const InlineChunkManifestHtmlWebpackPlugin = require('inline-chunk-manifest-html-webpack-plugin');

//keep it here,but could not get to work for sass...
const MiniCssExtractPlugin = require("mini-css-extract-plugin");


/* finds an index of babel rules in array of webpack rules */
/*
   {
   'ruleIdx':'',
   'useIdx':''
   }
 */

function getIdx_RulesByLoader (inRulesArr,
                               IS_DEV,
                               IS_WEB,
                               loaderStr,
                               extentionRegExTest) {

  let jsRulesBabelLoaderIdx = -1;
  let useIdx=-1;
  jsRulesBabelLoaderIdx=inRulesArr.findIndex(
    (rule) =>{
      if (rule.test // rule.test is a reg expr 
          && rule.test.exec
          && rule.test.exec(extentionRegExTest)
          && rule.use)
        {
          useIdx=rule.use.findIndex(
            (useItem)=> {
              if (useItem.options
                  && useItem.loader.includes(loaderStr) ){
                return true;
              }
            }
          );
          /*return true if useIdx is a valid index */
          return (useIdx>-1);
        }
    }
  );

  const res={
    'ruleIdx':jsRulesBabelLoaderIdx,
    'useIdx':useIdx
  };

  return res;
}





module.exports = {
  modify(baseConfig, secondArg, webpack) {

    const {target, dev}=secondArg;
    /* make a copy of config */
    const config = Object.assign({}, baseConfig);


    const IS_NODE = target === 'node';
    const IS_WEB = target === 'web';
    const IS_PROD = !dev;
    const IS_DEV = dev; 


    const MYpostCssLoader = {
      loader: 'postcss-loader',
      options: {
        ident: 'postcss',
        sourceMap: IS_DEV,
        plugins: () => [
          autoprefixer({
            browsers: ['>1%',
                       'last 4 versions',
                       'Firefox ESR',
                       'not ie < 9'],
          }),
        ],
      },
    };



    const MYscssLoader = {
      loader: 'sass-loader',
      options: {
        includePaths: [path.resolve(__dirname, './node_modules')],
        sourceMap: IS_DEV
      }};


    const MYcssLoader = IS_NODE ?
                        {loader:"css-loader"}
                       :{
                         loader: "css-loader",
                         options: {
                           minimize: !IS_DEV,
                           sourceMap: IS_DEV,
                           importLoaders: 1,
                           localIdentName:
IS_DEV?'[path]__[name]___[local]':undefined,
                         }
                       };


    /* 
       MiniCssExtractPlugin
       plugin should be used only on 
       production builds without style-loader 
       in the loaders chain, especially if you 
       want to have HMR in development.
     */

    const newSaasRule= {
      test: /\.(sass|scss)$/,
      exclude:[path.resolve(__dirname, './node_modules')],
      use: IS_NODE
         ? [MYcssLoader, MYscssLoader]
         : IS_DEV
         ? [
           'style-loader',
           MYcssLoader,
           MYpostCssLoader,
           MYscssLoader
         ]
          :[
            //'style-loader',
            MYcssLoader,            
            //cannot get this to work      MiniCssExtractPlugin.loader,
            MYpostCssLoader,
            MYscssLoader
          ]
    };//end of newSaasRule


    config.module.rules.push(newSaasRule);


    /* make babel to transply My symlinked directors
       This is relevant to My seetup (others may not have symlinks..)
       and from some directories containing react native modules
       @start<strong i="10">@step</strong>:1
     */

    /* match with config-override.js on the csr side */
    config.resolve.alias['web_common'] = path.resolve('./src/wc.src');
    config.resolve.alias['app_src'] = path.resolve('./src/app.src');
    config.resolve.alias['rnjs_common'] = path.resolve('./src/js.app');
    //config.resolve.alias.AppStyles$ = path.resolve('./src/app.src/styles/AppStyles')


    //copied from cra config
    //Probably not needed, 
    config.resolve.alias['babel-runtime']=path.dirname(require.resolve('babel-runtime/package.json'));


    /*
     *  add ./src to module resolver so you can import
     *  modules with absolute path
     *  again, this might not be of use to others...
     */
    config.resolve.modules.push('./src');


    let resOfBabelRule=getIdx_RulesByLoader(config.module.rules,
                                            IS_DEV,
                                            IS_WEB,
                                            'babel-loader', //loader name
                                            './testFileNm.js' //test file name for regex
    );



    /* noticed besides my sources, I also had to add react-native-vector-icons
    this was not the only change for RN-vector-icons though, but other changes
    for RN-vector icons are in babel related rules outside of this config file */
    const pathsToMySourcesArr=
      [
        fs.realpathSync(paths.appSrc+'/js.app'),
        fs.realpathSync(paths.appSrc+'/app.src'),
        fs.realpathSync(paths.appSrc+'/wc.src'),
        fs.realpathSync(paths.appNodeModules+'/react-native-vector-icons'),
        fs.realpathSync(paths.appNodeModules+'/react-native-vector-icons/node_modules'),
      ];



    config.module.rules[resOfBabelRule.ruleIdx]
          .include
          .push(...pathsToMySourcesArr);//use spread to push invidiual elements

    //this is a must 
    config.resolve.symlinks=false;

    /* react native vector icons @start<strong i="11">@step</strong>:1 */

    const newRNVectorIconsRule={
      test: /\.ttf$/,
      loader: require.resolve("file-loader"), // or directly file-loader
      include: fs.realpathSync(paths.appNodeModules+'/react-native-vector-icons')
    };

    config.module.rules.push(newRNVectorIconsRule);

    /* react native vector icons @end<strong i="12">@step</strong>:1 */


    if (IS_WEB) {
      if ( !IS_DEV ) {
        config.plugins.push( new BundleAnalyzerPlugin( {
          analyzerMode: "static",
          reportFilename: "webpack-report.html",
          openAnalyzer: false,
        } ) );
      }
    }



    /*
     * I share some of my react components with my
     * react native part of the system
     * So  UsefulComponent.web.js   is for web
     *  UsefulCompoenent.android.js is for android
     * Usefulcomponent.ios.js is for IOS
     *
     * By the way, react's CRA allows for web.js convention
     * so this should probably be a feature of razzle too
     * rather than a customization
     */
    config.resolve.extensions = config.resolve.extensions.concat([
      '.web.js'
    ]);

    return config;

  },
};

рдореИрдВ рдЗрд╕реЗ рдХрд╛рдо рдХрд░рдиреЗ рдореЗрдВ рдХрд╛рдордпрд╛рдм рд░рд╣рд╛, рдорджрдж рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рджред рдореИрдВ рдЬрд▓реНрдж рд╣реА рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рд╛рде рдПрдХ рдкреАрдЖрд░ рдмрдирд╛рдКрдВрдЧрд╛ред

рдХреНрдпрд╛ рдЖрдк рдПрдХ рдЙрджрд╛рд╣рд░рдг рдкреНрд░рджрд╛рди рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ @ MaxGoh

рдЗрд╕рдХреЗ рд▓рд┐рдП рдереЛрдбрд╝рд╛ рджреЗрд░ рд╣реЛ рдЪреБрдХреА рд╣реИ, рд▓реЗрдХрд┐рди рдпрд╣рд╛рдВ рдореЗрд░реЗ рд▓рд┐рдП рдХреНрдпрд╛ рдХрд╛рдо рдХрд┐рдпрд╛ рд╣реИ:

const path = require("path");

module.exports = {
    modify(config, { target, dev }, webpack) {
        for (const rule of config.module.rules) {
            if (rule.test && rule.test.toString() === "/\\.module\\.css$/") {
                const scss = { ...rule };

                scss.test = /\.scss$/;
                scss.include = path.join(__dirname, "src");
                scss.use.push({ loader: "sass-loader" });

                config.module.rules.push(scss);

                break;
            }
        }

        return config;
    }
};
рдХреНрдпрд╛ рдпрд╣ рдкреГрд╖реНрда рдЙрдкрдпреЛрдЧреА рдерд╛?
0 / 5 - 0 рд░реЗрдЯрд┐рдВрдЧреНрд╕